zoukankan      html  css  js  c++  java
  • 模板整理——图论部分

    - 图论

    - 最短路算法1

    - 最短路算法2

    • Floyd 算法(全源最短路)((mathcal O(n^3))
    #include"iostream"
    #include"cstdio"
    #include"cmath"
    using namespace std;
    
    #define MAXN 105
    
    int e[MAXN][MAXN];
    int n,m;
    int u,v,w;
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) e[i][j]=1000000000;
    	for(int i=1;i<=n;i++) e[i][i]=0;
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&u,&v,&w);
    		e[u][v]=min(e[u][v],w);
    	}
    	for(int k=1;k<=n;k++)//注意枚举顺序
    	{
    		for(int j=1;j<=n;j++)
    		{
    			for(int i=1;i<=n;i++)
    			{
    				e[i][j]=min(e[i][j],e[i][k]+e[k][j]);
    			}
    		}
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=n;j++) printf("%d ",e[i][j]);
    		puts("");
    	}
    	return puts(""),0;
    }
    
    • Dijkstra (单源最短路)(朴素实现为 (mathcal O(n^2)),经过优化(一般是堆优化)可以做到 (mathcal O(nlog n)),但不可以处理负权边)
    #include"iostream"
    #include"cstdio"
    #include"cmath"
    #include"queue"
    using namespace std;
    
    #define MAXN 100005 
    
    int n,m,s;
    int u,v,c;
    int dis[MAXN],vis[MAXN];
    struct node
    {
    	int to,nxt,w;
    }e[MAXN<<1];
    int head[MAXN],cnt=0;
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
    
    void add(int u,int v,int w){e[++cnt].to=v,e[cnt].w=w,e[cnt].nxt=head[u],head[u]=cnt;}
    
    void dij()
    {
    	while(!q.empty())
    	{
    		int u=q.top().second;
    		q.pop();
    		if(vis[u]) continue;
    		vis[u]=1;
    		for(int i=head[u];i;i=e[i].nxt)
    		{
    			int j=e[i].to;
    			if(dis[j]>dis[u]+e[i].w)
    			{
    				dis[j]=dis[u]+e[i].w;
    				q.push(make_pair(dis[j],j));
    			}
    		}
    	}
    	return;
    }
    
    int main()
    {
    	scanf("%d%d%d",&n,&m,&s);
    	for(int i=1;i<=m;i++) scanf("%d%d%d",&u,&v,&c),add(u,v,c);
    	for(int i=1;i<=n;i++) dis[i]=0x7fffffff;
    	dis[s]=0,q.push(make_pair(0,s));
    	dij();
    	for(int i=1;i<=n;i++) printf("%d ",dis[i]);
    	return puts(""),0;
    }
    
    • SPFA(单源最短路)(是对 Bellman-Ford 算法的一种优化,在随机数据下期望复杂度是 (mathcal O(kn)),但容易被卡成 (mathcal O(n^2)),故慎用,但优势是可以处理负权边)
    #include"iostream"
    #include"cstdio"
    #include"cmath"
    #include"queue"
    using namespace std;
    
    #define MAXN 100005 
    
    int n,m,s;
    int u,v,c;
    int dis[MAXN],vis[MAXN];
    struct node
    {
    	int to,nxt,w;
    }e[MAXN<<1];
    int head[MAXN],cnt=0;
    queue<int>q;
    
    void add(int u,int v,int w){e[++cnt].to=v,e[cnt].w=w,e[cnt].nxt=head[u],head[u]=cnt;}
    
    void SPFA()
    {
    	while(!q.empty())
    	{
    		int u=q.front();
    		q.pop();
    		vis[u]=0;
    		for(int i=head[u];i;i=e[i].nxt)
    		{
    			int j=e[i].to;
    			if(dis[j]>dis[u]+e[i].w)
    			{
    				dis[j]=dis[u]+e[i].w;
    				if(!vis[j]) q.push(j),vis[j]=1;
    			}
    		}
    	}
    	return;
    }
    
    int main()
    {
    	scanf("%d%d%d",&n,&m,&s);
    	for(int i=1;i<=m;i++) scanf("%d%d%d",&u,&v,&c),add(u,v,c);
    	for(int i=1;i<=n;i++) dis[i]=0x7fffffff;
    	dis[s]=0,q.push(s);
    	SPFA();
    	for(int i=1;i<=n;i++) printf("%d ",dis[i]);
    	return puts(""),0;
    }
    

    - 最小生成树(MST 问题)

    • Kruskal ((mathcal O(mlog m))
    #include"algorithm"
    #include"iostream"
    #include"cstdio"
    #include"cmath"
    using namespace std;
    
    int n,m;
    int sum,tot;
    int fa[5005];
    struct node
    {
    	int u,v,w;
    }e[200005];
    
    bool cmp(node n,node m){return n.w<m.w;}
    
    void init(int n){for(int i=1;i<=n;i++) fa[i]=i;}
    int getf(int u){return fa[u]=(fa[u]==u)?u:getf(fa[u]);}
    
    int merge(int u,int v)
    {
    	int t1=getf(u),t2=getf(v);
    	if(t1^t2){fa[t2]=t1;return 1;}
    	return 0;
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	init(n);
    	for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    	sort(e+1,e+m+1,cmp);
    	for(int i=1;i<=m;i++)
    	{
    		if(merge(e[i].u,e[i].v))
    		{
    			tot++,sum+=e[i].w;
    			if(tot==n-1) break;
    		}
    	}
    	if(tot<n-1) puts("orz");
    	else printf("%d
    ",sum);
    	return 0;
    }
    
    • Prim(使用堆优化 (mathcal O(nlog n))
    #include"algorithm"
    #include"iostream"
    #include"cstdio"
    #include"cmath"
    #include"queue"
    using namespace std;
    
    #define MAXN 200005
    
    int n,m;
    int sum,tot;
    int u,v,w;
    struct node
    {
        int to,nxt,w;
    }e[MAXN<<1];
    int head[MAXN],cnt=0;
    int dis[MAXN],vis[MAXN];
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
    
    void add(int u,int v,int w){e[++cnt].to=v,e[cnt].w=w,e[cnt].nxt=head[u],head[u]=cnt;}
    
    int Prim()
    {
    	while(!q.empty()&&tot!=n)
    	{
    		int u=q.top().second,c=q.top().first;
    		q.pop();
    		if(vis[u]) continue;
    		vis[u]=1;
    		tot++,sum+=c;
    		for(int i=head[u];i;i=e[i].nxt)
    		{
    			int j=e[i].to;
    			if(dis[j]>e[i].w) dis[j]=e[i].w,q.push(make_pair(dis[j],j));
    		}
    	}
    	if(tot==n) return 1;//注意这里指的是n个点而非边 
    	else 0;
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&u,&v,&w);
    		add(u,v,w),add(v,u,w);
    	}
    	for(int i=1;i<=n;i++) dis[i]=0x7fffffff;
    	dis[1]=0,q.push(make_pair(0,1));
    	int flag=Prim();
    	if(!flag) puts("orz");
    	else printf("%d
    ",sum);
    	return 0;
    }
    

    - 负环判断(mathcal O(kn))

    利用玄学的已死的 没死光的 SPFA 进行判断。

    #include"iostream"
    #include"cstring"
    #include"cstdio"
    #include"queue"
    #include"cmath"
    using namespace std;
    
    #define MAXN 2005
    #define inf 0x7fffffff
    #define read(x) scanf("%d",&x)
    #define mem(s) memset(s,0,sizeof(s))
    
    int n,m;
    int u,v,w;
    int t,dis[MAXN],len[MAXN];
    int vis[MAXN];
    queue<int> q;
    struct node
    {
        int to,nxt,w;
    }e[MAXN<<2];
    int head[MAXN],cnt=0;
    
    void add(int u,int v,int w){e[++cnt].to=v,e[cnt].w=w,e[cnt].nxt=head[u];head[u]=cnt;}
    
    int SPFA()
    {
        while(!q.empty())
        {
            int u=q.front();
            q.pop(),vis[u]=0;
            for(int i=head[u];i;i=e[i].nxt)
            {
                int j=e[i].to;
                if(dis[j]>dis[u]+e[i].w)
                {
                    dis[j]=dis[u]+e[i].w,len[j]=len[u]+1;
                    if(len[j]>n) return 1;
                    if(!vis[j]) vis[j]=1,q.push(j);
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        read(t);
        while(t--)
        {
            read(n),read(m);
            mem(vis),mem(len),mem(head),mem(e);
            while(!q.empty()) q.pop();
            cnt=0;
            for(int i=1;i<=m;i++)
            {
            	read(u),read(v),read(w);
            	if(w>=0) add(v,u,w);
            	add(u,v,w);
    		}
            for(int i=1;i<=n;i++) dis[i]=inf;
            dis[1]=0,vis[1]=1,q.push(1);
            (SPFA())?puts("YES"):puts("NO");
        }
        return 0;
    }
    

    - 差分约束系统(mathcal O(kn))

    #include"iostream"
    #include"cstdio"
    #include"cmath"
    using namespace std;
    
    #define MAXN 5005
    #define read(x) scanf("%d",&x)
    
    int n,m;
    int x,y,z;
    struct node
    {
    	int to,nxt,w;
    }e[MAXN<<1];
    int head[MAXN],cnt=0;
    int dis[MAXN],vis[MAXN];
    int cou[MAXN]={0},que[MAXN*MAXN],he=1,ta=1;
    
    void add(int u,int v,int w)
    {
    	e[++cnt].to=v;
    	e[cnt].nxt=head[u];
    	e[cnt].w=w;
    	head[u]=cnt;
    }
    
    void SPFA()
    {
    	que[1]=0,vis[0]=1,dis[0]=0;
    	while(he>=ta)
    	{
    		int u=que[ta++];
    		vis[u]=0;
    		for(int i=head[u];i;i=e[i].nxt)
    		{
    			int j=e[i].to;
    			if(dis[j]>dis[u]+e[i].w)
    			{
    				dis[j]=dis[u]+e[i].w,cou[j]=cou[u]+1;
    				if(!vis[j]) que[++he]=j,vis[j]=1;
    				if(cou[j]>=n+2){puts("NO");return;}
    			}	
    		}	
    	}
    	for(int i=1;i<=n;i++) printf("%d ",dis[i]);
    	puts("");
    	return;
    }
    
    int main()
    {
    	read(n),read(m);
    	for(int i=1;i<=m;i++) read(x),read(y),read(z),add(y,x,z);
    	for(int i=1;i<=n;i++) add(0,i,0);
    	for(int i=1;i<=n;i++) dis[i]=1e9;
    	SPFA();
    	return 0;
    }
    

    - 树的直径

    • 两次 dfs((mathcal O(n))
    #include"iostream"
    #include"cstdio"
    #include"cmath"
    #include"cstring"
    using namespace std;
    
    #define MAXN 10005
    #define read(x) scanf("%d",&x)
    
    int n,u,v;
    int len=0,pos;
    struct node
    {
        int to,nxt;
    }e[MAXN<<1];
    int head[MAXN],cnt=0;
    
    void add(int u,int v){e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt;}
    
    void dfs(int cur,int fa,int stp)
    {
        if(stp>len) len=stp,pos=cur;
        for(int i=head[cur];i;i=e[i].nxt)
        {
            int j=e[i].to;
            if(j==fa) continue;
            dfs(j,cur,stp+1);
        }
    }
    
    int main()
    {
        read(n);
        for(int i=1;i<n;i++) read(u),read(v),add(u,v),add(v,u);
        dfs(1,0,0),len=0,dfs(pos,0,0);
        printf("%d
    ",len);
        return 0;
    }
    
    • 树形 dp((mathcal O(n))
    #include"iostream"
    #include"cstdio"
    #include"cmath"
    #include"cstring"
    using namespace std;
    
    #define MAXN 10005
    #define read(x) scanf("%d",&x)
    
    int n,u,v;
    int dp[MAXN],ans=0;
    struct node
    {
        int to,nxt;
    }e[MAXN<<1];
    int head[MAXN],cnt=0;
    
    void add(int u,int v){e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt;}
    
    void dfs(int cur,int fa)
    {
        int maxn=0,maxnn=0;
        for(int i=head[cur];i;i=e[i].nxt)
        {
            int j=e[i].to;
            if(j==fa) continue;
            dfs(j,cur);
            if(maxn<=dp[j]+1) maxnn=maxn,maxn=dp[j]+1;
            else if(maxnn<dp[j]+1) maxnn=dp[j]+1;
        }
        dp[cur]=maxn,ans=max(ans,maxn+maxnn);
    }
    
    int main()
    {
        read(n);
        for(int i=1;i<n;i++) read(u),read(v),add(u,v),add(v,u);
        dfs(1,0);
        printf("%d
    ",ans);
        return 0;
    }
    

    - 树的重心((mathcal O(n))

    这题模板题是一道私题,我就不放了,这里只放代码。

    #include"iostream"
    #include"cstdio"
    #include"cstring"
    #include"algorithm"
    using namespace std;
    
    #define read(x) scanf("%d",&x)
    #define MAXN 500005
    
    int n;
    int d[MAXN],num,minx=0x7fffffff;
    struct node 
    {
    	int to,nxt;
    }e[MAXN<<1];
    int head[MAXN],cnt=0;
    int x,y,c=0,cen[15];
    
    void add(int u,int v)
    {
    	e[++cnt].to=v;
    	e[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    
    int dfs(int cur,int fa)
    {
    	d[cur]=1;
    	int maxn=0;
    	for(int i=head[cur];i;i=e[i].nxt)
    	{
    		int j=e[i].to;
    		if(j==fa) continue;
    		int now=dfs(j,cur);
    		maxn=max(maxn,now);
    		d[cur]+=now;
    	}
    	maxn=max(maxn,n-d[cur]);
    	if(maxn<minx) minx=maxn,num=cur,c=1,cen[c]=cur;
    	else if(maxn==minx) c++,cen[c]=cur;
    	return d[cur];
    }
    
    int main()
    {
    	read(n);
    	for(int i=1;i<n;i++) read(x),read(y),add(x,y),add(y,x);
    	dfs(1,0);
    	sort(cen+1,cen+c+1);
    	for(int i=1;i<=c;i++) printf("%d ",cen[i]);
    	return puts(""),0;
    }
    

    - 最近公共祖先(LCA)

    • 倍增((mathcal O(nlog n))

    这是传统写法,然而我不会。

    • tarjan(离线做法)((mathcal O(nalpha(n)+q))
    #include"iostream"
    #include"cstdio"
    #include"cmath"
    using namespace std;
    
    #define MAXN 500005
    
    int n,root,qe;
    int u,v;
    int f[MAXN],vis[MAXN];
    struct node
    {
    	int to,nxt;
    }e[MAXN<<1];
    int head[MAXN],cnt=0;
    struct query
    {
    	int to,nxt,id;
    }q[MAXN<<1];
    int sta[MAXN],cntt=0;
    int ans[MAXN];
    
    void add1(int u,int v){e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt;}
    void add2(int u,int v,int rt){q[++cntt].to=v,q[cntt].nxt=sta[u],q[cntt].id=rt,sta[u]=cntt;}
    
    void init(int n){for(int i=1;i<=n;i++) f[i]=i,vis[i]=0;}
    int getf(int u){return f[u]=(f[u]==u)?u:getf(f[u]);}
    void merge(int u,int v){int t1=getf(u),t2=getf(v);if(t1^t2) f[t2]=t1;}
    
    void dfs(int cur,int fa)
    {
    	vis[cur]=1; 
    	for(int i=head[cur];i;i=e[i].nxt) 
    	{
    		int j=e[i].to;
    		if(j==fa) continue;
    		dfs(j,cur);
    		merge(cur,j);//千千万万别写反了 
    	}
    	for(int i=sta[cur];i;i=q[i].nxt)
    	{
    		int j=q[i].to;
    		if(vis[j]) ans[q[i].id]=getf(j);
    	}
    	return;
    }
    
    int main()
    {
    	scanf("%d%d%d",&n,&qe,&root);
    	init(n);
    	for(int i=1;i<n;i++) scanf("%d%d",&u,&v),add1(u,v),add1(v,u);
    	for(int i=1;i<=qe;i++) scanf("%d%d",&u,&v),add2(u,v,i),add2(v,u,i);
    	dfs(root,root);
    	for(int i=1;i<=qe;i++) printf("%d
    ",ans[i]);
    	return 0;
    }
    
    • 树链剖分((mathcal O(nlog n))
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    using namespace std;
    
    #define read(x) scanf("%d",&x)
    #define MAXN 500005
    
    int top[MAXN],dep[MAXN],son[MAXN],vis[MAXN],f[MAXN],tot[MAXN];
    struct node
    {
    	int to,nxt;
    }e[MAXN<<1];
    int head[MAXN],cnt=0;
    int n,m,root,l,r;
    
    void add(int u,int v)
    {
    	e[++cnt].to=v;
    	e[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    
    int dfsa(int cur,int deep)
    {
    	vis[cur]=1;
    	dep[cur]=deep;
    	tot[cur]=1;
    	son[cur]=0;
    	int maxn=0;
    	for(int i=head[cur];i;i=e[i].nxt)
    	{
    		int j=e[i].to;
    		if(vis[j]) continue;
    		f[j]=cur;
    		int now=dfsa(j,deep+1);
    		if(now>maxn) maxn=now,son[cur]=j;
    		tot[cur]+=now;
    	}
    	return tot[cur];
    }
    
    void dfsb(int cur,int topf)
    {
    	vis[cur]=1;
    	top[cur]=topf;
    	if(son[cur]) dfsb(son[cur],topf);
    	for(int i=head[cur];i;i=e[i].nxt)
    	{
    		int j=e[i].to;
    		if(vis[j]) continue;
    		dfsb(j,j);
    	}
    	return;
    }
    
    int lca(int x,int y)
    {
    	while(top[x]!=top[y])
    	{
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		x=f[top[x]];
    	}
    	return dep[x]<dep[y]?x:y;
    }
    
    int main()
    {
    	read(n),read(m),read(root);
    	for(int i=1;i<n;i++)
    	{
    		read(l),read(r);
    		add(l,r),add(r,l);
    	}
    	memset(vis,0,sizeof(vis));
    	f[root]=root;
    	dfsa(root,1);
    	memset(vis,0,sizeof(vis));
    	dfsb(root,root);
    	for(int i=1;i<=m;i++)
    	{
    		read(l),read(r);
    		printf("%d
    ",lca(l,r));
    	}	
    	return 0; 
    }
    
    • ST 表((mathcal O(nlog n))

    学那么多干啥,有两种方法就够了/kk。

    - 缩点(tarjan)((mathcal O(n+m))

    缩的就是你,强联通分量!

    #include"iostream"
    #include"cstdio"
    #include"cmath"
    #include"cstring"
    using namespace std;
    
    #define read(x) scanf("%d",&x)
    #define MAXN 10005
    #define mem(s) memset(s,0,sizeof(s))
    
    int n,m;
    int head[MAXN],cnt=0;
    int cou=0,a[MAXN],id=0;
    struct node
    {
    	int to,nxt;
    }e[MAXN*10];
    int be[MAXN],si[MAXN],val[MAXN],vis[MAXN];
    int low[MAXN],num[MAXN];
    int x[MAXN*10],y[MAXN*10];
    int s[MAXN],top=0;
    int q[MAXN],rt=0,ta=1,in[MAXN];
    int dp[MAXN],ans=0;
    
    void add(int u,int v)
    {
    	e[++cnt].to=v;
    	e[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    
    void dfs(int cur)
    {
    	low[cur]=num[cur]=++id;
    	vis[cur]=1,s[++top]=cur;
    	for(int i=head[cur];i;i=e[i].nxt)
    	{
    		int j=e[i].to;
    		if(!vis[j]) dfs(j);
    		if(!be[j]) low[cur]=min(low[cur],low[j]);
    	}
    	if(low[cur]==num[cur])
    	{
    		cou++;
    		while(1)
    		{
    			int j=s[top--];
    			be[j]=cou,val[cou]+=a[j],si[cou]++;
    			if(j==cur) break;
    		}
    	}	
    }
    
    int main()
    {
    	read(n),read(m);
    	for(int i=1;i<=n;i++) read(a[i]);
    	for(int i=1;i<=m;i++)
    	{
    		read(x[i]),read(y[i]);
    		add(x[i],y[i]);
    	}
    	for(int i=1;i<=n;i++) if(!vis[i]) dfs(i);
    	cnt=0,mem(head),mem(e);
    	for(int i=1;i<=m;i++) if(be[x[i]]!=be[y[i]]) add(be[x[i]],be[y[i]]),in[be[y[i]]]++;
    	for(int i=1;i<=cou;i++) if(!in[i]) q[++rt]=i,dp[i]=val[i],ans=max(ans,dp[i]);
    	while(ta<=rt)
    	{
    		int u=q[ta];
    		ta++;
    		for(int i=head[u];i;i=e[i].nxt)
    		{
    			int j=e[i].to;
    			in[j]--;
    			dp[j]=max(dp[j],dp[u]+val[j]),ans=max(ans,dp[j]);
    			if(!in[j]) q[++rt]=j;
    		}
    	}
    	printf("%d
    ",ans);
    	return 0;
    }
    

    - 割点(tarjan)((mathcal O(n+m))

    #include"algorithm"
    #include"iostream"
    #include"cstdio"
    #include"cmath"
    using namespace std;
    
    #define MAXN  20005
    #define read(x) scanf("%d",&x)
    
    int n,m;
    int low[MAXN],num[MAXN],vis[MAXN];
    int head[MAXN],cnt=0;
    int c=0;
    struct node
    {
        int to,nxt;
    }e[MAXN*10];
    int u,v;
    int id=0;
    int child=0;
    int ma[MAXN];
    
    void add(int u,int v){e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt;}
    
    void dfs(int cur,int fa)
    {
        num[cur]=low[cur]=++id;
        vis[cur]=1;
    	int child=0;
        for(int i=head[cur];i;i=e[i].nxt)
        {
            int j=e[i].to;
            if(!vis[j]) 
    		{
    			child++;
    			dfs(j,cur);
            	low[cur]=min(low[cur],low[j]);
        		if(fa!=cur&&low[j]>=num[cur]&&!ma[cur]) c++,ma[cur]=1;
    		}
    		else if(j!=fa) low[cur]=min(low[cur],num[j]); 
    	}
    	if(cur==fa&&child>=2&&!ma[cur]) c++,ma[cur]=1;
        return;
    }
    
    int main()
    {
        read(n),read(m);
        for(int i=1;i<=m;i++) read(u),read(v),add(u,v),add(v,u);
        for(int i=1;i<=n;i++) if(!vis[i]) dfs(i,i);
        printf("%d
    ",c);
        for(int i=1;i<=n;i++) if(ma[i]) printf("%d ",i);
        return puts(""),0;
    }
    

    无向图缩点用 tarjan 割点类似的方法实现。

    割边(桥)的判断方法是 low[j]>num[cur],但不需要特判根节点。

    - 二分图匹配

    • 匈牙利算法((mathcal O(ne))
    #include"iostream"
    #include"cstdio"
    #include"cmath"
    using namespace std;
    
    #define MAXN 505
    #define read(x) scanf("%d",&x)
    
    int n,m,k;
    int u,v;
    struct node
    {
        int to,nxt;
    }e[50005];
    int head[MAXN],cnt=0;
    int mark[MAXN],vis[MAXN];
    int ans=0;
    
    void add(int u,int v){e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt;}
    
    bool dfs(int cur)
    {
        for(int i=head[cur];i;i=e[i].nxt)
        {
            int j=e[i].to-n;
            if(vis[j]) continue;
            vis[j]=1;
            if(!mark[j]||dfs(mark[j])){mark[j]=cur;return true;}
        }
        return false;
    }
    
    int main()
    {
        read(n),read(m),read(k);
        for(int i=1;i<=k;i++) read(u),read(v),add(u,n+v);
        for(int i=1;i<=n;i++)
        {
         	for(int j=1;j<=m;j++) vis[j]=0;
         	if(dfs(i)) ans++;
        }
        return printf("%d
    ",ans),0;
    }
    
    • Dinic((mathcal O(nsqrt{e}))

    看什么看我又不会网络流。

  • 相关阅读:
    Nosql database
    NoSQL
    nodejs and db
    Nodejs and json
    Nodejs异步
    HTTP-304 NOT Modified
    Origin null is not allowed by Access-Control-Allow-Origin
    nodejs MVC
    solr 亿万级数据查询性能測试
    iOS8 对开发人员来说意味着什么?
  • 原文地址:https://www.cnblogs.com/tlx-blog/p/13899778.html
Copyright © 2011-2022 走看看