Better man

改变性格 改变命运!

 

usaco telecow

求最小点集,可以通过最小割集转化,把点拆开变成边,这样就转化成了求最小割集;
注意把点拆开时边的转变:把每个点i拆成两个点i1,i2,这两个点之间建立一条边权为1的有向弧。对于原图中边(i,j),建立(i2,j1)和(j2,i1)两条边权为∞的有向弧。对于每个点i(非c1,c2),把边(i1,i2)去掉,求最大流,记为nowflow,记当前找到的最小割集中元素的数量为cnt。如果 netflow-cnt=nowflow+1,那么点i一定是最小割集中的割点,记录下来。否则将边(i1,i2)重新加上。直到 cnt=netflow,当前找的集合就是最小割集。
 1 #include<iostream>
 2 using namespace std;
 3 int n,m,s,t;
 4 int graph[101*2][101*2];//残留网络
 5 int cp[101*2][202];
 6 int Edmonds_Karp(int s,int t)
 7 {
 8       int flow=0;
 9       int cp[101*2];
10       int pre[101*2];
11       int que[100000];
12       while(true)
13       {
14             cp[s]=INT_MAX;
15             memset(pre,0,sizeof(pre));
16             int head=0,tail=1;que[0]=s; 
17             while(head!=tail)
18             {
19                   int i=que[head++];
20                   for(int j=1;j<=2*n;j++)    //节点从0算起
21                         if(j != i && !pre[j] && graph[i][j]>0)
22                         {
23                               cp[j]=min(cp[i],graph[i][j]);
24                               que[tail++]=j;
25                               pre[j]=i;
26                         }
27             }
28             if(pre[t]==0)break;
29             int i=t;
30             while(i!=s)
31             {
32                   int j=pre[i];
33                   graph[j][i]-=cp[t];
34                   graph[i][j]+=cp[t];
35                   i=j;
36             }
37             flow+=cp[t];
38       }
39       return flow;
40 }
41 int main()
42 {
43       int a,b;
44       freopen("telecow.in","r",stdin);
45       freopen("telecow.out","w",stdout);
46       scanf("%d%d%d%d",&n,&m,&s,&t);
47       for(int i=1;i<=n;++i)
48             graph[2*i-1][2*i]=1;
49       for(int i=1;i<=m;++i)
50       {
51             scanf("%d%d",&a,&b);
52             graph[2*b][2*a-1]=graph[2*a][2*b-1]=INT_MAX;
53       }
54       for(int i=1;i<=n;++i)
55             graph[2*t][2*i-1]=graph[2*i][s*2-1]=0;
56       memcpy(cp,graph,sizeof(graph));
57       int Max;
58       printf("%d\n",Max=Edmonds_Karp(2*s,2*t-1));
59       bool flag=1;
60      for(int i=1;i<=n;++i)
61       {
62             if(i==s||i==t)continue;
63             memcpy(graph,cp,sizeof(cp));
64             graph[2*i-1][2*i]=0;
65             int tmp=Edmonds_Karp(2*s,2*t-1);
66             cp[2*i-1][2*i]=1;
67             if(tmp+1==Max)
68             {
69                   if(flag)
70                   {
71                         printf("%d",i);
72                         flag=0;
73                   }
74                   else printf(" %d",i);
75                   cp[2*i-1][2*i]=0;
76                   Max=tmp;
77             }
78       }
79      printf("\n");
80       return 0;
81 }
82 

posted on 2009-02-03 19:37 SHFACM 阅读(193) 评论(0)  编辑 收藏 引用 所属分类: ACM


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

统计

常用链接

留言簿(2)

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜