题意:
目标人物T和S只要能间接联络到对方就算可以联络,如果T通过A和S联系,如果A换号码了,就切断了与T和S的联系,T和S就无法联系了,现在让我们找出最小要几个人(T和S不能发生事故)发生事故可以使S和T切断联系。
归纳题意:
判断给的无向图中至少去掉几个顶点才能使s和t不联通。
思路:
先判断s和t是否直接可以连接,如果可以,输出no answer下面就不用再继续判断了
如何拆点?把一个点拆成两个(流入、流出),连一条权值flow=1的边(其实我感觉遇到求解网络流题目只要有给出一幅图或者矩阵形式那么就需要进行拆点)
确定源点和汇点:源点st=0、汇点en=2*n+1,源点与s连权值为inf的边,t与汇点连权值为inf的边。
s与s'',t与t''连权值为inf的边(保证自己和自己是不会失去联系)。
假设i和j有边相连。则i''和j连权值为inf的边。j''与i连权值为inf的边。
跑最大流之后求得的流量即为点的个数。
然后编号从小到大枚举每一个点。尝试去掉这个点(即仅仅进不出)。又一次建图再跑最大流。
看最大流是否会减小。假设减小了,就是要去掉的点。记录下来最后输出就能够了。
AC代码:
1 #include<string.h>
2 #include<iostream>
3 #include<stdio.h>
4 #include<algorithm>
5 #include<queue>
6 #include<vector>
7 #include<map>
8 #include<cmath>
9 using namespace std;
10 #define inf inf
11 const int N=220;
12 typedef long long ll;
13 #define inf 0x3f3f3f3f
14
15 int s,t,st,en,n,tot;
16 bool book[N];
17 int a[N][N],head[10*N],dep[10*N],cur[10*N];
18 vector<int>out;
19
20 struct node
21 {
22 int v,flow,nextt;
23 } e[N*N*10];
24
25 void add(int u,int v,int flow)
26 {
27 tot++;
28 //nextt[tot]=head[u];
29 e[tot].nextt=head[u];
30 head[u]=tot;
31 // e[tot].u=u;
32 e[tot].v=v;
33 e[tot].flow=flow;
34
35 tot++;
36 // nextt[tot]=head[v];
37 e[tot].nextt=head[v];
38 head[v]=tot;
39 //e[tot].u=v;
40 e[tot].v=u;
41 e[tot].flow=0;
42 }
43
44 int dfs(int u,int flow)
45 {
46 if(u==en)
47 return flow;
48 for(int &i=cur[u]; i!=-1; i=e[i].nextt) //注意这里的&符号,这样i增加的同时也能改变cur[u]的值,达到记录当前弧的目的
49 {
50 if((dep[e[i].v]==dep[u]+1)&&e[i].flow>0)
51 {
52 int di=dfs(e[i].v,min(flow,e[i].flow));
53 if(di>0)
54 {
55 e[i].flow-=di;
56 e[i^1].flow+=di;
57 return di;
58 }
59 }
60 }
61 return 0;
62 }
63
64 bool bfs()
65 {
66 if(st==en)
67 return 0;
68 queue<int>Q;
69 while(!Q.empty())
70 Q.pop();
71 memset(dep,-1,sizeof(dep));
72 dep[st]=1;
73 Q.push(st);
74 while(!Q.empty())
75 {
76 int u=Q.front();
77 Q.pop();
78 for (int i=head[u]; i!=-1; i=e[i].nextt)
79 {
80 if ((e[i].flow>0)&&(dep[e[i].v]==-1))
81 {
82 dep[e[i].v]=dep[u]+1;
83 Q.push(e[i].v);
84 }
85 }
86 }
87 if(dep[t]!=-1)
88 return 1;
89 return 0;
90 }
91
92 int dinic()
93 {
94 int sum=0;
95 while(bfs())
96 {
97 for(int i=st; i<=en; i++)
98 cur[i]=head[i];
99 int di;
100 while(di=dfs(st,inf))
101 sum+=di;
102 }
103 return sum;
104 }
105
106 void build()
107 {
108 memset(head,-1,sizeof(head));
109 tot=-1;
110 add(st,s,inf);
111 add(t+n,en,inf);
112 for(int i=1; i<=n; i++)
113 {
114 if(book[i]==0)
115 add(i,i+n,1);
116 for(int j=1; j<=n; j++)
117 {
118 if(a[i][j])
119 add(i+n,j,inf);
120 }
121 }
122 add(s,s+n,inf);
123 add(t,t+n,inf);
124 }
125
126 int main()
127 {
128 while(~scanf("%d %d %d",&n,&s,&t))
129 {
130 tot=-1,st=0,en=2*n+1;
131 memset(book,0,sizeof(book));
132 memset(head,-1,sizeof(head));
133 for(int i=1; i<=n; i++)
134 {
135 for(int j=1; j<=n; j++)
136 scanf("%d",&a[i][j]);
137 }
138 if(a[s][t])
139 printf("NO ANSWER!\n");
140 else
141 {
142 build();
143 int ans=dinic();
144 printf("%d\n",ans);
145 if(ans==0)
146 continue;
147 int tmp=ans;
148 for(int i=1; i<=n; i++)
149 {
150 if(i==s||i==t) continue;
151 book[i]=1;
152 build();
153 int now=dinic();
154 if(now<tmp)
155 {
156 out.push_back(i);
157 tmp=now;
158 }
159 else
160 book[i]=0;
161 }
162 for(int i=0; i<out.size()-1; i++)
163 printf("%d ",out[i]);
164 printf("%d\n",out[out.size()-1]);
165 }
166
167
168 }
169 return 0;
170 }