[蒟蒻修炼计划][模板]匈牙利算法

JSOI写匈牙利的时候写炸了QAQ,我要好好补基础。

时间复杂度:O(m√n)

 1 #include<set>
 2 #include<cmath>
 3 #include<ctime>
 4 #include<stack>
 5 #include<queue>
 6 #include<cstdio>
 7 #include<vector>
 8 #include<cstring>
 9 #include<cstdlib>
10 #include<iostream>
11 #include<algorithm>
12 #define N 3001
13 #define M 200001
14 using namespace std;
15 struct graph{
16     int nxt,to;
17 }e[M];
18 int g[N],fr[N],n,m,cnt;
19 bool u[N];
20 inline void addedge(int x,int y){
21     e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;
22 }
23 inline bool match(int x){
24     for(int i=g[x];i;i=e[i].nxt)
25         if(!u[e[i].to]){
26             u[e[i].to]=true;
27             if(!fr[e[i].to]||match(fr[e[i].to])){
28                 fr[e[i].to]=x;return true;
29             }
30         }
31     return false;
32 }
33 inline int hungary(){
34     int ret=0;
35     for(int i=1;i<=n;i++){
36         fill(u+1,u+1+n,false);
37         if(match(i)) ret++;
38     }
39     return ret;
40 }
41 inline void init(){
42     scanf("%d%d",&n,&m);
43     for(int i=1,j,k;i<=m;i++){
44         scanf("%d%d",&j,&k);
45         addedge(j,k);
46     }
47     printf("%d",hungary());
48 }
49 int main(){
50     freopen("hungary.in","r",stdin);
51     freopen("hungary.out","w",stdout);
52     init();
53     fclose(stdin);
54     fclose(stdout);
55 }
时间: 2024-10-24 04:25:09

[蒟蒻修炼计划][模板]匈牙利算法的相关文章

[蒟蒻修炼计划][模板] 2-SAT

昨天早上在准备省队集训,发现自己连2-SAT是什么都不知道,于是一早上都投身于2-SAT模板中,终于有个结果. 思路如下: 1.根据条件表达式建边: 2.缩环: 3.判断是否可行: 4.根据缩完环的图反向建边: 5.拓扑排序进行染色(1表示true,2表示false). 1 /*假设输入是无空格无括号的的c++条件表达式且未知数用编号代替*/ 2 #include<set> 3 #include<cmath> 4 #include<ctime> 5 #include&l

[蒟蒻修炼计划][模板]μ函数

省队集训看着台上的老师讲了一上午的莫比乌斯反演,整个人都是懵的,因为我看不清黑板和投影!!! 回家后本来想晚上自学完的,却奈何自己是个拖延症患者,只敲了μ函数(说多了都是泪QAQ) 代码的思路如下: 1.算质因数个数时因为有将1算上,所以每次都需要将符号取反: 2.为什么这样做能算出μ(a)=0呢?证明如下(如果有错可以指出,但别打我QAQ): ①先证明:已知a=p1*p2*p3*...*pn*pi(1<=i<=n且p为质数) 则μ(a)=μ(1)μ(p1)+μ(p2)+...μ(n)+μ(p

[蒟蒻修炼计划][bzoj1854][SCOI2010]游戏

Description 一个装备有两个属性,一个装备只能被使用一次,一次使用一种属性.攻击boss时需按属性1.属性2.属性3...属性k的顺序使用,问k最大为多少. Input 输入的第一行是一个整数N,表示有N种装备.接下来N行,是对这N种装备的描述,每行2个数字,表示第i种装备的2个属性值. Output 输出一行,包括1个数字,表示k. Sample Input 3 1 2 3 2 4 5 Sample Output 2 HINT 1<=属性值<=10000,N < =10000

蒟蒻修炼计划-KMP 模板

1 #include<cmath> 2 #include<queue> 3 #include<stack> 4 #include<cstdio> 5 #include<vector> 6 #include<string> 7 #include<cstring> 8 #include<cstdlib> 9 #include<iostream> 10 #include<algorithm>

[蒟蒻修炼计划][谜之吐槽]FJ省夏令营day1

T1 Description 给出n个矩形的顶点坐标(每个矩形的底边都在x轴上),求这n个矩形所组成图形的轮廓线的顶点. Input 第一行一个整数n,表示矩形个数. 以下n行,每行3个整数,分别表示矩形的x坐标区间及矩形的高度h[i]. Output 第一行一个整数m,表示轮廓线顶点个数. 以下m行,每行一个坐标表示轮廓线上的顶点.从左到右遍历轮廓线并顺序输出顶点.第一个和最后一个节点的y坐标必然为0. Sample Input 2 3 0 2 4 1 3 Sample Output 6 0

[蒟蒻修炼计划][bzoj3670][Noi2014]动物园

Description 已知一个字符串S,对于字符串S的前i个字符构成的子串,既是它的后缀同时又是它的前缀,并且该后缀与该前缀不重叠,将这种字符串的数量记作num[i]. 求mod 10^9+7. Input 第1行仅包含一个正整数n,表示测试数据的组数.随后n行,每行描述一组测试数据.每组测试数据仅含有一个字符串S,S的定义详见题目描述.数据保证S中仅含小写字母.输入文件中不会包含多余的空行,行末不会存在多余的空格. Output 包含n行,每行描述一组测试数据的答案,答案的顺序应与输入数据的

[蒟蒻修炼计划][学习笔记]数论(二)

乘法逆元:若,则称为在意义下的乘法逆元. 本文介绍乘法逆元的三种求法. 扩展欧几里得求逆元 因为,所以设满足, 则可以用扩展欧几里得求关于的方程的一组解,即求出b. inline int exgcd(int a,int b,int &x,int &y){ if(!b){ x=1;y=0;return a; } int ret=exgcd(b,a%b,y,x); y-=a/b*x;return ret; } inline int inver{ r=exgcd(a,p,b,q); if(r!=

[蒟蒻修炼计划][学习笔记]数论(一)

扩展欧几里得 求二元一次不定方程的一组解. 当时,有一组解 : 当时,因为 , 所以设满足, 则 , 整理得 . 所以. 就可以在求gcd的过程中得到一组解. inline int exgcd(int a,int b,int &x,int &y){ if(!b){ x=1;y=0;return a; } else{ int ret=exgcd(b,a%b,y,x); y-=a/b*x;return ret; } } 欧拉函数 欧拉函数的定义:小于等于的正整数中与互质的数的个数. 当时,:

[蒟蒻修炼计划][谜之吐槽]常州集训day3

T1 Description 有K个石子,石子只能放在N条水平线与M条竖直线构成的网格的交点上. 求用K个石子最多能找到多少四边平行于坐标轴的长方形,它的四个角上都恰好放着一枚石子. Input 第一行三个整数N,M,K. Output 一个非负整数,即最多的满足条件的长方形数量. Sample Input 3 3 8 Sample Output 5 HINT N<=30000,保证任意两点不重合,K<=N*M Solution 很显然,最佳的方案长这样: xxx…xxx