题目链接:http://poj.org/problem?id=1815
In modern society, each person has his own friends. Since all the people are very busy, they communicate with each other only by phone. You can assume that people A can keep in touch with people B, only if
1. A knows B's phone number, or
2. A knows people C's phone number and C can keep in touch with B.
It's assured that if people A knows people B's number, B will also know A's number.
Sometimes, someone may meet something bad which makes him lose touch with all the others. For example, he may lose his phone number book and change his phone number at the same time.
In this problem, you will know the relations between every two among N people. To make it easy, we number these N people by 1,2,...,N. Given two special people with the number S and T, when some people meet bad things, S may lose touch with T. Your job is to compute the minimal number of people that can make this situation happen. It is supposed that bad thing will never happen on S or T.
题目描述:n个人,给出一些关系(两个人之间直接联系或可以间接联系),现在破坏一些人,使S和T这两个人不能联系。求出最小的人数(输出字典序最小的方案)。
算法分析:最小割解之,这个不用说了。重点在于怎么求解字典序最小:由于节点较少,我们可以一一枚举节点u,然后去掉u->u'后求解最小割是否会使最小割变小,是则必须删掉此边。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 0x7fffffff 10 using namespace std; 11 const int maxn=500,M=100000; 12 13 int n,from,to; 14 struct node 15 { 16 int v,flow; 17 int next; 18 } edge[M*4],save[M*4]; 19 int head[maxn],edgenum; 20 21 void add(int u,int v,int flow) 22 { 23 edge[edgenum].v=v ;edge[edgenum].flow=flow ; 24 edge[edgenum].next=head[u] ;head[u]=edgenum++; 25 26 edge[edgenum].v=u ;edge[edgenum].flow=0; 27 edge[edgenum].next=head[v] ;head[v]=edgenum++; 28 } 29 30 int d[maxn]; 31 int bfs() 32 { 33 memset(d,0,sizeof(d)); 34 d[from]=1; 35 queue<int> Q; 36 Q.push(from); 37 while (!Q.empty()) 38 { 39 int u=Q.front() ;Q.pop() ; 40 for (int i=head[u] ;i!=-1 ;i=edge[i].next) 41 { 42 int v=edge[i].v; 43 if (!d[v] && edge[i].flow) 44 { 45 d[v]=d[u]+1; 46 Q.push(v); 47 if (v==to) return 1; 48 } 49 } 50 } 51 return 0; 52 } 53 54 int dfs(int u,int flow) 55 { 56 if (u==to || flow==0) return flow; 57 int cap=flow; 58 for (int i=head[u] ;i!=-1 ;i=edge[i].next) 59 { 60 int v=edge[i].v; 61 if (d[v]==d[u]+1 && edge[i].flow) 62 { 63 int x=dfs(v,min(cap,edge[i].flow)); 64 edge[i].flow -= x; 65 edge[i^1].flow += x; 66 cap -= x; 67 if (cap==0) return flow; 68 } 69 } 70 return flow-cap; 71 } 72 73 int dinic() 74 { 75 int ans=0; 76 while (bfs()) ans += dfs(from,inf); 77 return ans; 78 } 79 80 int an[maxn][maxn]; 81 int main() 82 { 83 while(scanf("%d%d%d",&n,&from,&to)!=EOF) 84 { 85 bool flag=false; 86 for(int i=1;i<=n;i++) 87 { 88 for(int j=1;j<=n;j++) 89 { 90 scanf("%d",&an[i][j]); 91 } 92 } 93 if(an[from][to]) 94 { 95 printf("NO ANSWER!\n"); 96 continue; 97 } 98 memset(head,-1,sizeof(head)); 99 edgenum=0; 100 for (int i=1 ;i<=n ;i++) 101 { 102 if (i!=from && i!=to) 103 add(i,i+n,1); 104 for (int j=1 ;j<=n ;j++) 105 { 106 if (an[i][j]&&i!=j) 107 { 108 if (i==from) 109 add(i,j,inf); 110 else if (i!=to) 111 add(i+n,j,inf); 112 } 113 } 114 } 115 memcpy(save,edge,sizeof(node)*edgenum); 116 int ans=dinic(); 117 printf("%d\n",ans); 118 for (int i=1 ;i<=n ;i++) 119 { 120 if (i!=from && i!=to) 121 for (int j=head[i] ;j!=-1 ;j=edge[j].next) 122 { 123 if (edge[j].flow==0 && edge[j].v==i+n) 124 { 125 save[j].flow=save[j^1].flow=0; 126 memcpy(edge,save,sizeof(node)*edgenum); 127 if (dinic()!=ans-1) 128 { 129 save[j].flow=1; 130 save[j^1].flow=0; 131 continue; 132 } 133 if (flag) 134 printf(" "); 135 else 136 flag=true; 137 printf("%d",i); 138 ans--; 139 break; 140 } 141 } 142 } 143 printf("\n"); 144 } 145 return 0; 146 }