題目大意:給出一個無向圖,要求刪除盡量少的點,使給定的2點間不再連通,並輸出字典序最小的方案
題型:圖論-網絡流
此題難點在於建圖,後面就是套網絡流的模板.
將點看成邊,例如第i個點可以看成一條有向邊<i*2-1,i*2>,容量為1.
如果j點和i點鄰接,那麼新建2條容量為無窮大的有向邊<i*2,j*2-1>,<j*2,i*2-1>.
然後應用最大流最小割定理,求最大流即為第一問答案.
接著枚舉刪除每一個點i(即刪除有向邊),看最大流是否減少1,如果是則該點在最小割中,然後真的把這一點刪點.
枚舉完每個點之後別忘了將殘量網絡還原.
至於為什麼要這樣建圖, 一時間說不清楚......
Executing...
Test 1: TEST OK [0.008 secs, 3852 KB]
Test 2: TEST OK [0.014 secs, 3852 KB]
Test 3: TEST OK [0.005 secs, 3852 KB]
Test 4: TEST OK [0.022 secs, 3852 KB]
Test 5: TEST OK [0.011 secs, 3852 KB]
Test 6: TEST OK [0.019 secs, 3852 KB]
Test 7: TEST OK [0.019 secs, 3852 KB]
Test 8: TEST OK [0.014 secs, 3852 KB]
Test 9: TEST OK [0.032 secs, 3852 KB]
Test 10: TEST OK [0.046 secs, 3852 KB]
Test 11: TEST OK [0.068 secs, 3852 KB]
All tests OK.
Your program ('telecow') produced all correct answers! This is your
submission #3 for this problem. Congratulations!
1 #include <iostream>
2 #include <cstring>
3 #include <queue>
4 #include <stdio.h>
5 #define msize 210
6 #define INF 1000000000
7 using namespace std;
8
9 int origin[msize][msize]={0};
10 int r[msize][msize]={0}; //殘留網絡,初始為原圖
11 bool visited[msize];
12 int pre[msize];
13 int m,nVertex; //n條邊,m個頂點
14
15 bool bfs(int s,int t) //尋找一條從s到t的增廣路,若找到,返回true
16 {
17 int p;
18 queue<int> Q;
19 memset(pre,-1,sizeof(pre));
20 memset(visited,false,sizeof(visited));
21
22 pre[s]=s;
23 visited[s]=true;
24 Q.push(s);
25
26 while (!Q.empty())
27 {
28 p=Q.front(),Q.pop();
29 for (int i=1; i<=nVertex; i++)
30 {
31 if (r[p][i]>0&&!visited[i])
32 {
33 pre[i]=p;
34 visited[i]=true;
35 if (i==t) return true;
36 Q.push(i);
37 }
38 }
39 }
40
41 return false;
42 }
43
44 int maxFlow(int s,int t)
45 {
46 int flow=0,d;
47
48 while (bfs(s,t))
49 {
50 d=INF;
51 for (int i=t; i!=s; i=pre[i]) d=min(d,r[pre[i]][i]);
52 for (int i=t; i!=s; i=pre[i]) r[pre[i]][i] -= d, r[i][pre[i]] += d;
53 flow += d;
54 }
55 return flow;
56 }
57
58 int main()
59 {
60 freopen("telecow.in","r",stdin);
61 freopen("telecow.out","w",stdout);
62 int s,e,c;
63
64 cin>>nVertex>>m>>s>>e;
65 nVertex*=2;
66 for(int i=0;i<m;i++)
67 {
68 int a,b;
69 scanf("%d%d",&a,&b);
70 r[a*2-1][a*2]=1;
71 r[b*2-1][b*2]=1;
72 r[a*2][b*2-1]=INF;
73 r[b*2][a*2-1]=INF;
74 }
75 memcpy(origin,r,sizeof r);
76 int maxflow=maxFlow(s*2,e*2-1);
77 int sum=maxflow;
78 memcpy(r,origin,sizeof r);
79 printf("%d\n",maxflow);
80
81 bool first=true;
82 int cnt=0;
83 for(int i=1;i<=nVertex/2;i++) // 模擬刪掉第i個點
84 {
85 if(i==s || i==e)
86 continue;
87 if(cnt==sum)
88 {
89 break;
90 }
91 memcpy(origin,r,sizeof r);
92 r[i*2-1][i*2]=0;
93
94 if(maxFlow(s*2,e*2-1)+1==maxflow)
95 {
96 maxflow--;
97 cnt++;
98 if(first)
99 {
100 first=false;
101 }
102 else
103 {
104 printf(" ");
105 }
106 printf("%d",i);
107 memcpy(r,origin,sizeof r);
108 r[i*2-1][i*2]=0;
109 }
110 else
111 {
112 memcpy(r,origin,sizeof r);
113 }
114 }
115 cout<<endl;
116 return 0;
117 }