【题意】:给出n个城市,m条边,问最少摧毁多少个城市使得城市1到城市n的最短路大于k。

【题解】:先用floyd求出点对的最短路,判断哪些点是在长度少于等于k的路上,然后把每个城市拆点,容量为1,加入原图上的边,容量为inf。
               求最小割即为答案。

【代码】:
  1 #include "iostream"
  2 #include "cstdio"
  3 #include "cstring"
  4 #include "algorithm"
  5 #include "vector"
  6 #include "queue"
  7 #include "cmath"
  8 #include "string"
  9 #include "cctype"
 10 #include "map"
 11 #include "iomanip"
 12 using namespace std;
 13 #define pb push_back
 14 #define mp make_pair
 15 #define fi first
 16 #define se second
 17 #define lc(x) (x << 1)
 18 #define rc(x) (x << 1 | 1)
 19 #define lowbit(x) (x & (-x))
 20 #define ll long long
 21 #define maxn 1050
 22 #define maxm 1000050
 23 const int inf = 1 << 30;
 24 int maz[55][55];
 25 int n, m, k;
 26 int s, t;
 27 int eh[maxn], low[maxn], dist[maxn], pre[maxn], cur[maxn], tot, cnt[maxn];
 28 
 29 struct Edge {
 30     int u, v, cap, flow, next;
 31 }et[maxm];
 32 
 33 void init() {
 34     tot = 0;
 35     memset(eh, -1, sizeof(eh));
 36 }
 37 
 38 void add(int u, int v, int cap, int flow) {
 39     Edge e = {u, v, cap, flow, eh[u]};
 40     et[tot] = e;
 41     eh[u] = tot++;
 42 }
 43 
 44 void addedge(int u, int v, int cap) {
 45     add(u, v, cap, 0), add(v, u, 0, 0);
 46 }
 47 
 48 void floyd() {
 49     for(int k = 1; k <= n; k++) {
 50         for(int i = 1; i <= n; i++) {
 51             for(int j = 1; j <= n; j++) {
 52                 if(maz[i][k] != inf && maz[k][j] != inf)
 53                     maz[i][j] = min(maz[i][j], maz[i][k] + maz[k][j]);
 54             }
 55         }
 56     }
 57 }
 58 
 59 int isap(int s, int t, int n){
 60     int u, v, now, flow = 0;
 61     memset(dist, 0, sizeof(dist)); 
 62     memset(low, 0, sizeof(low));
 63     memset(cnt, 0, sizeof(cnt));
 64     for(u = 0 ; u <= n ; u ++) cur[u] = eh[u];
 65     low[s] = inf, cnt[0] = n, u = s;
 66     while(dist[s] < n) {
 67         for(now = cur[u]; now != -1; now = et[now].next)
 68             if(et[now].cap - et[now].flow && dist[u] == dist[ v = et[now].v ] + 1 ) break;
 69         if(now != -1) {
 70             cur[u] = pre[v] = now;
 71             low[v] = min(et[now].cap - et[now].flow, low[u]);
 72             u = v;
 73             if(u == t) {
 74                 for(; u != s; u = et[pre[u]].u){
 75                     et[pre[u]].flow += low[t];
 76                     et[pre[u]^1].flow -= low[t];
 77                 }
 78                 flow += low[t]; low[s] = inf;
 79             }
 80         } else {
 81             if(--cnt[dist[u]] == 0) break;
 82             dist[u] = n, cur[u] = eh[u];
 83             for(now = eh[u]; now != -1; now = et[now].next)
 84                 if(et[now].cap - et[now].flow && dist[u] > dist[et[now].v] + 1)
 85                     dist[u] = dist[ et[now].v ] + 1;
 86             cnt[dist[u]]++;
 87             if(u != s) u = et[pre[u]].u;
 88         }
 89     }
 90     return flow;
 91 }
 92 
 93 int main() {
 94     int u, v;
 95     while(~scanf("%d%d%d", &n, &m, &k)) {
 96         if(!n) break;
 97         s = 1, t = n;
 98         init();
 99         for(int i = 0; i < 55; i++)
100             for(int j = 0; j < 55; j++)
101                 maz[i][j] = inf;
102         for(int i = 0; i < m; i++) {
103             scanf("%d%d", &u, &v);
104             maz[u][v] = 1;
105         }
106         floyd();
107         for(int i = 2; i < n; i++) {
108             if(maz[s][i] + maz[i][t] <= k) {
109                 addedge(i, i + n, 1);
110             }
111         }
112         for(int i = 1; i <= n; i++) {
113             for(int j = 1; j <= n; j++) {
114                 if(maz[i][j] == 1) addedge(i + n, j, inf);
115             }
116         }
117         int ans = isap(s + n, t, 2 * n - 2);
118         cout << ans << endl;
119     }
120     return 0;
121 }
122