ZOJ 2182 Cable TV Network(无向图点割-最大流)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2182
题意:给出一个无向图,问最少删掉多少个顶点之后图变得不连通?
思路:将原图每个点拆点(i,i+n),连边<i,i+n,1>,对原图的边(u,v),连边<u+n,v,INF>,<v+n,u,INF>。然后对于每对顶点(i,j)跑最大流(i+n,j)。所有最大流的最小值即为答案。
struct node { int v,cap,next; }; node edges[N*10]; int head[N],e; int curedge[N],h[N],num[N],pre[N]; int s,t; void add(int u,int v,int cap) { edges[e].v=v; edges[e].cap=cap; edges[e].next=head[u]; head[u]=e++; } void Add(int u,int v,int cap) { add(u,v,cap); add(v,u,0); } int Maxflow(int s,int t,int n) { clr(h,0); clr(num,0); int i; FOR0(i,n+1) curedge[i]=head[i]; int u=s,Min,k,x,ans=0; while(h[u]<n) { if(u==t) { Min=INF*100; for(i=s;i!=t;i=edges[curedge[i]].v) { x=curedge[i]; if(edges[x].cap<Min) { Min=edges[x].cap; k=i; } } ans+=Min; u=k; for(i=s;i!=t;i=edges[curedge[i]].v) { x=curedge[i]; edges[x].cap-=Min; edges[x^1].cap+=Min; } } for(i=curedge[u];i!=-1;i=edges[i].next) { if(edges[i].cap>0&&h[u]==h[edges[i].v]+1) { break; } } if(i!=-1) { curedge[u]=i; pre[edges[i].v]=u; u=edges[i].v; } else { if(--num[h[u]]==0) break; curedge[u]=head[u]; x=n; for(i=head[u];i!=-1;i=edges[i].next) { k=edges[i].v; if(edges[i].cap>0&&h[k]<x) x=h[k]; } h[u]=x+1; num[x+1]++; if(u!=s) u=pre[u]; } } return ans; } int n,m; int a[55][55]; int visit[55]; void DFS(int u) { visit[u]=1; int i,v; FOR1(i,n) if(a[u][i]&&!visit[i]) { DFS(i); } } int ok() { clr(visit,0); DFS(1); int i; FOR1(i,n) if(!visit[i]) return 0; return 1; } int cal(int s,int t) { clr(head,-1); e=0; int i,j; FOR1(i,n) Add(i,i+n,1); FOR1(i,n) for(j=1;j<=n;j++) if(a[i][j]) { Add(i+n,j,INF); } return Maxflow(s+n,t,n+n+2); } int get() { int x=0; char c=getchar(); while(!isdigit(c))c=getchar(); while(isdigit(c)) { x=x*10+c-‘0‘; c=getchar(); } return x; } int main() { while(scanf("%d%d",&n,&m)!=-1) { if(m==0) { if(n==0) puts("0"); else if(n==1) puts("1"); else puts("0"); continue; } clr(a,0); int u,v,i; FOR0(i,m) { u=get(); v=get(); a[u+1][v+1]=a[v+1][u+1]=1; } if(!ok()) { puts("0"); continue; } int j; int ans=INF; FOR1(i,n) for(j=1;j<=n;j++) if(i!=j) { int x=cal(i,j); ans=min(ans,x); } if(ans==INF||ans==n-1) ans=n; PR(ans); } }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。