POJ 1815 最小割
题意:
n个人的两两关系矩阵,如果a认识b,则b认识a,且认识有传递性。给出一个s和一个t,问想让s不认识t,最少需要去掉多少人。
如果有解,输出字典序最小的解。
题解:
请特别注意0与NO ANSWER!的区别!
具体做法是:拆点限流,先求一次最小割为ans,然后从小到大枚举删除的点,重新建图再做最小割,如果当前结果比ans小,则更新ans,并把这个节点打上vis标记。
ps:已经打上vis标记的点不再参与之后重建图时
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstring> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <iostream> 5 #include <algorithm> 6 7 #define N 500 8 #define M 40000 9 #define INF 1e9 10 11 using namespace std; 12 13 int head[N],to[M],next[M],len[M]; 14 int q[M*4],layer[N]; 15 bool map[N][N],vis[N]; 16 int n,S,T,tt,ss,cnt; 17 18 inline void add(int u,int v,int w) 19 { 20 to[cnt]=v; len[cnt]=w; next[cnt]=head[u]; head[u]=cnt++; 21 to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++; 22 //printf("%d %d %d\n",u,v,w); 23 } 24 25 inline bool read() 26 { 27 memset(head,-1,sizeof head); cnt=0; 28 memset(vis,0,sizeof vis); 29 memset(map,0,sizeof map); 30 S=0; T=n+n+1; 31 32 for(int i=1;i<=n;i++) 33 for(int j=1;j<=n;j++) 34 scanf("%d",&map[i][j]); 35 if(map[ss][tt]) return false; 36 37 add(S,ss,INF); add(tt+n,T,INF); 38 for(int i=1;i<=n;i++) 39 { 40 if(i==ss||i==tt) add(i,i+n,INF); 41 else add(i,i+n,1); 42 } 43 for(int i=1;i<=n;i++) 44 for(int j=1;j<=n;j++) 45 if(map[i][j]&&i!=j) add(i+n,j,INF); 46 return true; 47 } 48 49 inline void rebuild(int u) 50 { 51 memset(head,-1,sizeof head); cnt=0; 52 add(S,ss,INF); add(tt+n,T,INF); 53 for(int i=1;i<=n;i++) 54 { 55 if(i==ss||i==tt) add(i,i+n,INF); 56 else if(i!=u&&!vis[i]) add(i,i+n,1); 57 } 58 for(int i=1;i<=n;i++) 59 { 60 if(i==u||vis[i]) continue; 61 for(int j=1;j<=n;j++) 62 if(map[i][j]&&j!=u&&i!=j&&!vis[j]) 63 add(i+n,j,INF); 64 } 65 } 66 67 inline bool bfs() 68 { 69 memset(layer,-1,sizeof layer); 70 int h=1,t=2,sta; 71 q[1]=S; layer[S]=0; 72 while(h<t) 73 { 74 sta=q[h++]; 75 for(int i=head[sta];~i;i=next[i]) 76 if(len[i]&&layer[to[i]]<0) 77 { 78 layer[to[i]]=layer[sta]+1; 79 q[t++]=to[i]; 80 } 81 } 82 return layer[T]!=-1; 83 } 84 85 inline int find(int u,int cur_flow) 86 { 87 if(u==T) return cur_flow; 88 int res=0,tmp; 89 for(int i=head[u];~i&&res<cur_flow;i=next[i]) 90 if(len[i]&&layer[to[i]]==layer[u]+1) 91 { 92 tmp=find(to[i],min(cur_flow-res,len[i])); 93 len[i]-=tmp; len[i^1]+=tmp; res+=tmp; 94 } 95 if(!res) layer[u]=-1; 96 return res; 97 } 98 99 inline void go() 100 { 101 int ans=0,num=0; 102 while(bfs()) ans+=find(S,INF); 103 if(!ans) 104 { 105 puts("0"); 106 return; 107 } 108 for(int i=1,res;i<=n;i++) 109 if(i!=ss&&i!=tt) 110 { 111 res=0; 112 rebuild(i); 113 while(bfs()) res+=find(S,INF); 114 if(ans>res) vis[i]=true,num++,ans=res; 115 } 116 printf("%d\n",num); 117 for(int i=1,sg=0;i<=n;i++) 118 if(vis[i]) 119 { 120 if(!sg) sg=true,printf("%d",i); 121 else printf(" %d",i); 122 } 123 puts(""); 124 } 125 126 int main() 127 { 128 while(scanf("%d%d%d",&n,&ss,&tt)!=EOF) 129 { 130 if(!read()) puts("NO ANSWER!"); 131 else go(); 132 } 133 return 0; 134 }
没有人能阻止我前进的步伐,除了我自己!