【题意】:给出一幅无向图,n个顶点m条边,每条边都有一定的长度和删除这条边的代价,给出s和t,问至少用多少代价删除一些边使得s到t的最短路变长。
【题解】:显然,我们要删的边必定是最短路上的边。所以先求一次最短路,并保留最短路上的边,若满足dist[u] + w(u,v) == dist[v],那么这条边就是最短路上的边。现在问题就转化为用最小的代价把s和t分割,这显然是个最小割的问题,求最大流即为ans。
【代码】:
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 using namespace std;
11 #define pb push_back
12 #define lc(x) (x << 1)
13 #define rc(x) (x << 1 | 1)
14 #define lowbit(x) (x & (-x))
15 #define ll long long
16 #define maxn 2000
17 #define maxm 50000
18 const int inf = 1 << 30;
19 int s, t, n, m;
20 struct Edge {
21 int u, v, w, cost, next;
22 }et[maxm];
23
24 struct edge {
25 int u, v, cap, flow, next;
26 }et2[maxm];
27
28 int eh[maxn], tot, dist[maxn];
29 bool visit[maxn];
30 int eh2[maxn], tot2, low[maxn], dist2[maxn], pre[maxn], cur[maxn], cnt[maxn];
31
32 void init() {
33 tot = 0;
34 tot2 = 0;
35 memset(eh, -1, sizeof (eh));
36 memset(eh2, -1, sizeof (eh2));
37 }
38
39 void addedge(int u, int v, int w, int cost) {
40 Edge e = {u, v, w, cost, eh[u]};
41 et[tot] = e;
42 eh[u] = tot++;
43 }
44
45 void add(int u, int v, int cap, int flow) {
46 edge e = {u, v, cap, flow, eh2[u]};
47 et2[tot2] = e;
48 eh2[u] = tot2++;
49 }
50
51 void addedge2(int u, int v, int cap) {
52 add(u, v, cap, 0), add(v, u, 0, 0);
53 }
54
55 void spfa(int s) {
56 for (int i = 0; i <= n; i++) visit[i] = false, dist[i] = inf, cnt[i] = 0;//dist[i] = -inf;
57 dist[s] = 0, visit[s] = true;
58 queue<int> que;
59 que.push(s);
60 while (!que.empty()) {
61 int u = que.front();
62 que.pop(), visit[u] = false;
63 for (int i = eh[u]; i != -1; i = et[i].next) {
64 int v = et[i].v, w = et[i].w;
65 if (dist[v] > w + dist[u]) {//dist[v] < w + dist[u]
66 dist[v] = w + dist[u];
67 if (!visit[v]) {
68 visit[v] = true;
69 que.push(v);
70 }
71 }
72 }
73 }
74 }
75
76 void build() {
77 for(int i = 0; i < tot; i++) {
78 int u = et[i].u, v = et[i].v, w = et[i].w, cost = et[i].cost;
79 if(dist[u] + w == dist[v]) {
80 addedge2(u, v, cost);
81 }
82 }
83 }
84
85 int isap(int s, int t, int n){
86 int u, v, now, flow = 0;
87 memset(dist2, 0, sizeof(dist2));
88 memset(low, 0, sizeof(low));
89 memset(cnt, 0, sizeof(cnt));
90 for(u = 0 ; u <= n ; u++) cur[u] = eh2[u];
91 low[s] = inf, cnt[0] = n, u = s;
92 while(dist2[s] < n) {
93 for(now = cur[u]; now != -1; now = et2[now].next)
94 if(et2[now].cap - et2[now].flow && dist2[u] == dist2[ v = et2[now].v ] + 1 ) break;
95 if(now != -1) {
96 cur[u] = pre[v] = now;
97 low[v] = min(et2[now].cap - et2[now].flow, low[u]);
98 u = v;
99 if(u == t) {
100 for(; u != s; u = et2[pre[u]].u){
101 et2[pre[u]].flow += low[t];
102 et2[pre[u]^1].flow -= low[t];
103 }
104 flow += low[t]; low[s] = inf;
105 }
106 } else {
107 if(--cnt[dist2[u]] == 0) break;
108 dist2[u] = n, cur[u] = eh2[u];
109 for(now = eh2[u]; now != -1; now = et2[now].next)
110 if(et2[now].cap - et2[now].flow && dist2[u] > dist2[et2[now].v] + 1)
111 dist2[u] = dist2[et2[now].v] + 1;
112 cnt[dist2[u]]++;
113 if(u != s) u = et2[pre[u]].u;
114 }
115 }
116 return flow;
117 }
118
119 int main() {
120 int u, v, w, c;
121 int Case = 1;
122 while(~scanf("%d%d", &n, &m)) {
123 if(!n && !m) break;
124 scanf("%d%d", &s, &t);
125 init();
126 for(int i = 0; i < m; i++) {
127 scanf("%d%d%d%d", &u, &v, &w, &c);
128 addedge(u, v, w, c);
129 addedge(v, u, w, c);
130 }
131 spfa(s);
132 build();
133 int ans = isap(s, t, n);
134 printf("Case %d: %d\n", Case++, ans);
135 }
136 return 0;
137 }
138