网络流24题 最小路径覆盖(DCOJ8002)
题目描述
给定有向图 G=(V,E) G = (V, E)G=(V,E)。设 P PP 是 G GG 的一个简单路(顶点不相交)的集合。如果 V VV 中每个顶点恰好在 P PP 的一条路上,则称 P PP 是 G GG 的一个路径覆盖。P PP 中路径可以从 V VV的任何一个顶点开始,长度也是任意的,特别地,可以为 0 00。G GG 的最小路径覆盖是 G GG 的所含路径条数最少的路径覆盖。
设计一个有效算法求一个有向无环图 G GG 的最小路径覆盖。
输入格式
第 1 11 行有 2 22 个正整数 n nn 和 m mm。n nn 是给定有向无环图 G GG 的顶点数,m mm 是 G GG 的边数。
接下来的 m mm 行,每行有 2 22 个正整数 u uu 和 v vv,表示一条有向边 (i,j) (i, j)(i,j)。
输出格式
从第 1 11 行开始,每行输出一条路径。
文件的最后一行是最少路径数。
样例
样例输入
11 12
1 2
1 3
1 4
2 5
3 6
4 7
5 8
6 9
7 10
8 11
9 11
10 11
样例输出
1 4 7 10 11
2 5 8
3 6 9
3
数据范围与提示
1≤n≤200,1≤m≤6000 1 \leq n \leq 200, 1 \leq m \leq 60001≤n≤200,1≤m≤6000
最小割 最大流
//Serene #include<algorithm> #include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> using namespace std; const int maxn=400+10,maxm=6010+maxn; int n,m,k,S,T,tot,ans,rb[maxn],rd[maxn]; bool pl[maxn];int v[maxn]; int aa;char cc; int read() { aa=0;cc=getchar(); while(cc<'0'||cc>'9') cc=getchar(); while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar(); return aa; } struct Node{ int x,y,cap,flow; }node[2*maxm]; int cur[maxn]; int fir[maxn],nxt[2*maxm],e=1; void add(int x,int y,int z) { node[++e].x=x;node[e].y=y;node[e].cap=z; nxt[e]=fir[x];fir[x]=e; node[++e].x=y;node[e].y=x;node[e].cap=0; nxt[e]=fir[y];fir[y]=e; } int zz[maxn],dis[maxn],s=1,t=0; bool BFS() { memset(dis,-1,sizeof(dis)); dis[S]=0; s=1,t=0;zz[++t]=S; int x,y; while(s<=t) { x=zz[s];s++; for(y=fir[x];y;y=nxt[y]) { if(node[y].flow>=node[y].cap||dis[node[y].y]!=-1) continue; dis[node[y].y]=dis[x]+1; zz[++t]=node[y].y; } } return dis[T]!=-1; } int DFS(int pos,int maxf) { if(pos==T||!maxf) return maxf; int rs=0,now; for(int &y=cur[pos];y;y=nxt[y]) { if(node[y].flow>=node[y].cap||dis[node[y].y]!=dis[node[y].x]+1) continue; now=DFS(node[y].y,min(maxf,node[y].cap-node[y].flow)); node[y].flow+=now; node[y^1].flow-=now; rs+=now; maxf-=now; } if(!rs) dis[pos]=-1; return rs; } int Dinic() { int rs=0; while(BFS()) { memcpy(cur,fir,sizeof(fir)); rs+=DFS(S,0x3f3f3f3f); } return rs; } int main() { n=read();m=read();tot=n; int x,y; S=2*n+1;T=S+1; for(int i=1;i<=n;++i) add(S,i,1),add(i+n,T,1); for(int i=1;i<=m;++i) { x=read();y=read(); add(x,y+n,1); } ans=tot-Dinic(); for(int i=2;i<=e;++i) { if(node[i].x<=n&&node[i].flow==1) { rb[node[i].x]=node[i].y-n; rd[node[i].y-n]=1; } } for(int i=1;i<=n;++i) if(!rd[i]){ x=i;printf("%d",i); while(rb[x]) printf(" %d",x=rb[x]); printf("\n"); } printf("%d",ans); return 0; }
弱者就是会被欺负呀