ACM-ICPC Live Archive 3031 Cable TV Network
求解无向图的点连通度,转化为网络流
详细的解释明天再写了
#include <cstdio> #include <cstring> #include <queue> using namespace std; #define N 60 #define min(a,b) a<b?a:b #define max(a,b) a>b?a:b #define INF 0x3f3f3f3f int first[10*N]; struct edge { int u,v,cap,flow,next; }e[N*N*N]; int nume; int n,m; void EK(int s ,int t ,int &MIN) { int FLOW=0; while(1) { queue<int>q; int a[10*N]; int p[10*N]; memset(a,0,sizeof(a)); memset(p,-1,sizeof(p)); a[s]=INF; while(!q.empty()) q.pop(); q.push(s); while(!q.empty()) { int u,v,cap,flow; u=q.front(); q.pop(); for(int k=first[u]; k!=-1; k=e[k].next) { v=e[k].v; cap=e[k].cap; flow=e[k].flow; if(!a[v] && cap>flow) //未访问且可增流 { a[v]=min(a[u] , cap-flow); p[v]=k; q.push(v); } } } if(!a[t]) break; //不可增广 for(int k=p[t]; k!=-1; k=p[e[k].u]) { e[k].flow += a[t]; e[k^1].flow -= a[t]; } FLOW += a[t]; } MIN=min(MIN,FLOW); } void init() { for(int i=0; i<nume; i++) e[i].flow=0; } void solve(int s) { int MIN=INF; for(int t=1; t<n; t++)//枚举汇点 { EK(s,t,MIN); init(); } if(MIN>=INF) printf("%d\n",n); else printf("%d\n",MIN); } void add(int u ,int v , int cap) { e[nume].u=u; e[nume].v=v; e[nume].cap=cap; e[nume].flow=0; e[nume].next=first[u]; first[u]=nume++; e[nume].u=v; e[nume].v=u; e[nume].cap=0; e[nume].flow=0; e[nume].next=first[v]; first[v]=nume++; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { if(m==0) { if(n==1)printf("1\n"); else printf("0\n"); continue; } memset(first,-1,sizeof(first)); nume=0; for(int i=0; i<n; i++) add(i,i+n,1); for(int i=0; i<m; i++) { int u,v; char s[20]; scanf("%s",s); sscanf(s+1,"%d",&u); for(int j=0; s[j]!='\0'; j++) if(s[j]==',') { sscanf(s+j+1,"%d",&v); break;} //拆点,拆为u,u+n, add(u+n,v,INF); add(v+n,u,INF); } solve(n); } return 0; }