USACO 5.4.5 Telecowmunication

题目大意:

给定一个无向图与两个点,问最少去掉几个点(不能去掉给定的点)能使这两个点不连通,并输出字典序最小的方案。
 
简单题解:
这个问题是要求该图的最小点割集,可以使用最小割最大流定理。
但是最小割是边的割,该怎么办呢?
 
拆点!将每个点拆成入点和出点。所有入边连到入点上,出边从出点连出,流量均为+INF。再在入点和出点间连一条流量为1的边。然后做最大流即为答案。
至于输出最小字典序方案的问题,可以参考milk6,从小到大枚举删点,若删去后流量减少了1,则输出。
 
我的代码:
 1 /*
 2 ID:t-x.h1
 3 LANG:C++
 4 TASK:telecow
 5 */
 6 #include<cstdio>
 7 #include<cstring>
 8 #define min(x,y) ((x)<(y)?(x):(y))
 9 FILE *fi=fopen("telecow.in","r"),*fo=fopen("telecow.out","w");
10 const int MAXn=2*(100+9),INF=99999999;
11 int n,s,t,g[MAXn][MAXn],r[MAXn][MAXn],save[MAXn][MAXn];
12 int gap[MAXn],d[MAXn];
13 int sap(int u,int flow)
14 {
15         if(u==t)
16                 return flow;
17         int i,tmp,ans=0;
18         for(i=1;i<=2*n;++i)
19                 if(r[u][i] && d[u]==d[i]+1)
20                 {
21                         tmp=sap(i,min(r[u][i],flow-ans));
22                         ans+=tmp,r[u][i]-=tmp,r[i][u]+=tmp;
23                         if(ans==flow)
24                                 return ans;
25                 }
26         if(d[s]>=2*n)
27                 return ans;
28         if(!--gap[d[u]])
29                 d[s]=2*n;
30         ++gap[++d[u]];
31         return ans;
32 }
33 int maxflow()
34 {
35         int tot=0;
36         memcpy(r,g,sizeof(r));
37         memset(gap,0,sizeof(gap));
38         memset(d,0,sizeof(d));
39         for(gap[0]=2*n;d[s]<2*n;)
40                 tot+=sap(s,INF);
41         return tot;
42 }
43 int main()
44 {
45         int m,i,j,k;
46         bool flag=1;
47         fscanf(fi,"%d%d%d%d",&n,&m,&s,&t);
48         s*=2,t=t*2-1;
49         for(i=1;i<=n;++i)
50                 g[2*i-1][2*i]=1;
51         for(i=1;i<=m;++i)
52         {
53                 fscanf(fi,"%d%d",&j,&k);
54                 g[2*j][2*k-1]=g[2*k][2*j-1]=INF;
55         }
56         fprintf(fo,"%d\n",k=maxflow());
57         memcpy(save,r,sizeof(r));
58         for(i=1;i<=n;++i)
59                 if(!save[2*i-1][2*i] && i!=s/2 && i!=(t+1)/2)
60                 {
61                         g[2*i-1][2*i]=0;
62                         if(maxflow()+1==k)
63                         {
64                                 memcpy(save,r,sizeof(r));
65                                 --k;
66                                 if(flag)
67                                         fprintf(fo,"%d",i),flag=0;
68                                 else
69                                         fprintf(fo," %d",i);
70                         }
71                         else
72                                 g[2*i-1][2*i]=1;
73                 }
74         fputc(10,fo);
75         fclose(fi);
76         fclose(fo);
77         return 0;
78 }

 

posted @ 2012-08-18 12:58  凌云七风  阅读(356)  评论(0编辑  收藏  举报