[AHOI2008]上学路线
这道题其实挺显然的。
首先dijkstra跑出最短路图,然后在最短路图上求最小割。
正确性显然。
需要注意的是,在新图中添加最短路图的边的时候,一定是跑完dijkstra再加边,如果边跑dijkstra边加边,得到的是最短路树,而不是图。我因为这个WA了好几发。
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 505; 21 const int maxe = 1.3e5 + 5; 22 inline ll read() 23 { 24 ll ans = 0; 25 char ch = getchar(), last = ' '; 26 while(!isdigit(ch)) {last = ch; ch = getchar();} 27 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 28 if(last == '-') ans = -ans; 29 return ans; 30 } 31 inline void write(ll x) 32 { 33 if(x < 0) x = -x, putchar('-'); 34 if(x >= 10) write(x / 10); 35 putchar(x % 10 + '0'); 36 } 37 38 int n, m; 39 struct Edge1 40 { 41 int nxt, to, t, c; 42 }e1[maxe << 1]; 43 int head1[maxn], ecnt1 = -1; 44 void addEdge1(int x, int y, int t, int c) 45 { 46 e1[++ecnt1] = (Edge1){head1[x], y, t, c}; 47 head1[x] = ecnt1; 48 } 49 50 struct Edge2 51 { 52 int nxt, from, to, cap, flow; 53 }e2[maxe << 2]; 54 int head2[maxn], ecnt2 = -1; 55 void addEdge2(int from, int to, int w) 56 { 57 e2[++ecnt2] = (Edge2){head2[from], from, to, w, 0}; 58 head2[from] = ecnt2; 59 e2[++ecnt2] = (Edge2){head2[to], to, from, 0, 0}; 60 head2[to] = ecnt2; 61 } 62 63 #define pr pair<int, int> 64 #define mp make_pair 65 bool in[maxn]; 66 int dis[maxn]; 67 void dijkstra(int s) 68 { 69 Mem(dis, 0x3f); dis[s] = 0; 70 priority_queue<pr, vector<pr>, greater<pr> > q; 71 q.push(mp(dis[s], s)); 72 while(!q.empty()) 73 { 74 int now = q.top().second; q.pop(); 75 if(in[now]) continue; 76 in[now] = 1; 77 for(int i = head1[now]; i != -1; i = e1[i].nxt) 78 { 79 if(dis[e1[i].to] > dis[now] + e1[i].t) 80 { 81 dis[e1[i].to] = dis[now] + e1[i].t; 82 q.push(mp(dis[e1[i].to], e1[i].to)); 83 } 84 } 85 } 86 } 87 88 int dis2[maxn]; 89 bool bfs() 90 { 91 Mem(dis2, 0); dis2[1] = 1; 92 queue<int> q; q.push(1); 93 while(!q.empty()) 94 { 95 int now = q.front(); q.pop(); 96 for(int i = head2[now]; i != -1; i = e2[i].nxt) 97 { 98 if(!dis2[e2[i].to] && e2[i].cap > e2[i].flow) 99 { 100 dis2[e2[i].to] = dis2[now] + 1; 101 q.push(e2[i].to); 102 } 103 } 104 } 105 return dis2[n]; 106 } 107 int cur[maxn]; 108 int dfs(int now, int res) 109 { 110 if(now == n || res == 0) return res; 111 int flow = 0, f; 112 for(int &i = cur[now]; i != -1; i = e2[i].nxt) 113 { 114 if(dis2[e2[i].to] == dis2[now] + 1 && (f = dfs(e2[i].to, min(res, e2[i].cap - e2[i].flow))) > 0) 115 { 116 e2[i].flow += f; e2[i ^ 1].flow -= f; 117 flow += f; res -= f; 118 if(res == 0) break; 119 } 120 } 121 return flow; 122 } 123 124 int minCut() 125 { 126 int flow = 0; 127 while(bfs()) 128 { 129 memcpy(cur, head2, sizeof(head2)); 130 flow += dfs(1, INF); 131 } 132 return flow; 133 } 134 135 int main() 136 { 137 Mem(head1, -1); Mem(head2, -1); 138 n = read(); m = read(); 139 for(int i = 1; i <= m; ++i) 140 { 141 int x = read(), y = read(), t = read(), c = read(); 142 addEdge1(x, y, t, c); addEdge1(y, x, t, c); 143 } 144 dijkstra(1); 145 for(int i = 1; i <= n; ++i) 146 for(int j = head1[i]; j != -1; j = e1[j].nxt) 147 if(dis[e1[j].to] == dis[i] + e1[j].t) addEdge2(i, e1[j].to, e1[j].c); 148 write(dis[n]), enter, write(minCut()), enter; 149 return 0; 150 }