Description

Gabiluso is one of the greatest spies in his country. Now he’s trying to complete an “impossible” mission ----- to make it slow for the army of City Colugu to reach the airport. City Colugu has n bus stations and m roads. Each road connects two bus stations directly, and all roads are one way streets. In order to keep the air clean, the government bans all military vehicles. So the army must take buses to go to the airport. There may be more than one road between two bus stations. If a bus station is destroyed, all roads connecting that station will become no use. What’s Gabiluso needs to do is destroying some bus stations to make the army can’t get to the airport in k minutes. It takes exactly one minute for a bus to pass any road. All bus stations are numbered from 1 to n. The No.1 bus station is in the barrack and the No. n station is in the airport. The army always set out from the No. 1 station. No.1 station and No. n station can’t be destroyed because of the heavy guard. Of course there is no road from No.1 station to No. n station.
Please help Gabiluso to calculate the minimum number of bus stations he must destroy to complete his mission.
 

Input

There are several test cases. Input ends with three zeros.
For each test case:
The first line contains 3 integers, n, m and k. (0< n <=50, 0< m<=4000, 0 < k < 1000) Then m lines follows. Each line contains 2 integers, s and f, indicating that there is a road from station No. s to station No. f. 
 

Output

For each test case, output the minimum number of stations Gabiluso must destroy.

 

题目大意:有n(n≤50)个点,起点1到终点n,有m条有向边(m≤4000)。现破坏掉若干起点和终点以外的点,使得从起点到终点经过的边数必须大于k条。问最少要破坏多少个点,保证从起点到终点没有边。

 

我们先来看一个可以AC但实际上错误的思路o(╯□╰)o(为什么错误还能AC啊?数据弱呗……)

思路:先求每个点到起点和终点的最短路径,然后每个点拆成两个点x、x',如果dis(s,x) + dis(x,t) ≤ k,那么建一条边x→x',容量为1(源点和汇点容量为无穷大)。对每条边(i, j),连一条边i'→j,容量为无穷大。求最小割。根据最大流最小割定理,最大流为答案。因为对于一点x,如果dis(s,x) + dis(x,t) > k,那么没必要破坏点x。那么问题就变成了最少破坏多少个点,使得从1到n必须要经过一个点,经过那个点的话从1到n必然会大于k。

先上代码(15MS):

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <queue>
  5 using namespace std;
  6 
  7 const int MAXN = 210;
  8 const int MAXE = 20010;
  9 const int INF = 0x3fff3fff;
 10 
 11 struct SAP {
 12     int head[MAXN], cur[MAXN], pre[MAXN], gap[MAXN], dis[MAXN];
 13     int to[MAXE], cap[MAXE], flow[MAXE], next[MAXE];
 14     int ecnt, n, st, ed;
 15 
 16     void init() {
 17         memset(head, 0, sizeof(head));
 18         ecnt = 2;
 19     }
 20 
 21     void add_edge(int u, int v, int c) {
 22         to[ecnt] = v; cap[ecnt] = c; flow[ecnt] = 0; next[ecnt] = head[u]; head[u] = ecnt++;
 23         to[ecnt] = u; cap[ecnt] = 0; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++;
 24         //printf("%d->%d %d\n", u, v, c);
 25     }
 26 
 27     void bfs() {
 28         memset(dis, 0x3f, sizeof(dis));
 29         queue<int> que; que.push(ed);
 30         dis[ed] = 0;
 31         while(!que.empty()) {
 32             int u = que.front(); que.pop();
 33             ++gap[dis[u]];
 34             for(int p = head[u]; p; p = next[p]) {
 35                 int v = to[p];
 36                 if(dis[v] > n && cap[p ^ 1]) {
 37                     dis[v] = dis[u] + 1;
 38                     que.push(v);
 39                 }
 40             }
 41         }
 42     }
 43 
 44     int Max_flow(int ss, int tt, int nn) {
 45         st = ss, ed = tt, n = nn;
 46         int ans = 0, minFlow = INF, u;
 47         for(int i = 0; i <= n; ++i) {
 48             cur[i] = head[i];
 49             gap[i] = 0;
 50         }
 51         u = pre[st] = st;
 52         bfs();
 53         while(dis[st] < n) {
 54             bool flag = false;
 55             for(int &p = cur[u]; p; p = next[p]) {
 56                 int v = to[p];
 57                 if(cap[p] > flow[p] && dis[v] + 1 == dis[u]) {
 58                     flag = true;
 59                     minFlow = min(minFlow, cap[p] - flow[p]);
 60                     pre[v] = u;
 61                     u = v;
 62                     if(u == ed) {
 63                         ans += minFlow;
 64                         while(u != st) {
 65                             u = pre[u];
 66                             flow[cur[u]] += minFlow;
 67                             flow[cur[u] ^ 1] -= minFlow;
 68                         }
 69                         minFlow = INF;
 70                     }
 71                     break;
 72                 }
 73             }
 74             if(flag) continue;
 75             int minDis = n - 1;
 76             for(int p = head[u]; p; p = next[p]) {
 77                 int v = to[p];
 78                 if(cap[p] > flow[p] && dis[v] < minDis) {
 79                     minDis = dis[v];
 80                     cur[u] = p;
 81                 }
 82             }
 83             if(--gap[dis[u]] == 0) break;
 84             gap[dis[u] = minDis + 1]++;
 85             u = pre[u];
 86         }
 87         return ans;
 88     }
 89 } G;
 90 
 91 struct SP {
 92     int head[MAXN], head2[MAXN], dis_st[MAXN], dis_ed[MAXN];
 93     int to[MAXE], next[MAXE], to2[MAXE], next2[MAXE];
 94     int ecnt, n, st, ed;
 95 
 96     void init(int ss, int tt, int nn) {
 97         memset(head, 0, sizeof(head));
 98         memset(head2, 0, sizeof(head2));
 99         ecnt = 2;
100         st = ss; ed = tt; n = nn;
101     }
102 
103     void add_edge(int u, int v) {
104         to[ecnt] = v; next[ecnt] = head[u]; head[u] = ecnt;
105         to2[ecnt] = u; next2[ecnt] = head2[v]; head2[v] = ecnt++;
106     }
107 
108     void make_dis_st() {
109         memset(dis_st, 0x3f, sizeof(dis_st));
110         queue<int> que; que.push(st);
111         dis_st[st] = 0;
112         while(!que.empty()) {
113             int u = que.front(); que.pop();
114             for(int p = head[u]; p; p = next[p]) {
115                 int v = to[p];
116                 if(dis_st[v] > n) {
117                     dis_st[v] = dis_st[u] + 1;
118                     que.push(v);
119                 }
120             }
121         }
122     }
123 
124     void make_dis_ed() {
125         memset(dis_ed, 0x3f, sizeof(dis_ed));
126         queue<int> que; que.push(ed);
127         dis_ed[ed] = 0;
128         while(!que.empty()) {
129             int u = que.front(); que.pop();
130             for(int p = head2[u]; p; p = next2[p]) {
131                 int v = to2[p];
132                 if(dis_ed[v] > n) {
133                     dis_ed[v] = dis_ed[u] + 1;
134                     que.push(v);
135                 }
136             }
137         }
138     }
139 
140     void make_G(int k) {
141         make_dis_st();
142         //for(int i = 1; i <= n; ++i) printf("%d ", dis_st[i]);
143         make_dis_ed();
144         //for(int i = 1; i <= n; ++i) printf("%d ", dis_ed[i]);
145         G.init();
146         G.add_edge(1, 1 + n, INF);
147         G.add_edge(n, n + n, INF);
148         for(int i = 2; i < n; ++i)
149             if(dis_st[i] + dis_ed[i] <= k) G.add_edge(i, i + n, 1);
150         for(int u = 1; u <= n; ++u) {
151             for(int p = head[u]; p; p = next[p]) {
152                 int v = to[p];
153                 G.add_edge(u + n, v, INF);
154             }
155         }
156     }
157 } T;
158 
159 int n, m, k, a, b;
160 
161 int main() {
162     while(scanf("%d%d%d", &n, &m, &k) != EOF) {
163         if(n == 0 && m == 0 && k == 0) break;
164         T.init(1, n, n);
165         while(m--) {
166             scanf("%d%d", &a, &b);
167             T.add_edge(a, b);
168         }
169         T.make_G(k);
170         printf("%d\n", G.Max_flow(1, n + n, n + n));
171     }
172 }
View Code

相关文章: