[AHOI 2006] 上学路线
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=1266
[算法]
首先 , 用Dijkstra求单源最短路
然后 , 建出这张图G的最短路图G’ , 答案即为G'的最小割
最大流最小割定理 : 最小割 = 最大流
直接求最大流即可
时间复杂度 : O(Dinic(N , M))
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 500010 const int inf = 2e9; struct edge { int to , w , nxt; } e[MAXN << 1]; int n , tot , m; int u[MAXN] , v[MAXN] , w[MAXN] , c[MAXN] , head[MAXN] , depth[MAXN] , dist[MAXN]; bool visited[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } inline void addedge(int u , int v , int w) { ++tot; e[tot] = (edge){v , w , head[u]}; head[u] = tot; } inline void addedgeF(int u , int v , int w) { ++tot; e[tot] = (edge){v , w , head[u]}; head[u] = tot; ++tot; e[tot] = (edge){u , 0 , head[v]}; head[v] = tot; } inline void dijkstra() { priority_queue< pair<int , int> , vector< pair<int , int> > , greater< pair<int , int> > > q; for (int i = 1; i <= n; i++) { dist[i] = inf; visited[i] = false; } dist[1] = 0; q.push(make_pair(0 , 1)); while (!q.empty()) { int cur = q.top().second; q.pop(); if (visited[cur]) continue; visited[cur] = true; for (int i = head[cur]; i; i = e[i].nxt) { int v = e[i].to , w = e[i].w; if (dist[cur] + w < dist[v]) { dist[v] = dist[cur] + w; q.push(make_pair(dist[v] , v)); } } } } inline bool bfs() { int l , r; static int q[MAXN]; memset(depth , 0 , sizeof(depth)); q[depth[l = r = 1] = 1] = 1; while (l <= r) { int cur = q[l++]; for (int i = head[cur]; i; i = e[i].nxt) { int v = e[i].to , w = e[i].w; if (w > 0 && !depth[v]) { depth[v] = depth[cur] + 1; q[++r] = v; } } } if (depth[n] > 0) return true; else return false; } inline int dinic(int u , int flow) { int rest = flow; if (u == n) return flow; for (int i = head[u]; i && rest; i = e[i].nxt) { int v = e[i].to , w = e[i].w; if (depth[v] == depth[u] + 1 && w > 0) { int k = dinic(v , min(rest , w)); if (!k) depth[v] = 0; e[i].w -= k; e[i ^ 1].w += k; rest -= k; } } return flow - rest; } int main() { read(n); read(m); for (int i = 1; i <= m; i++) { read(u[i]); read(v[i]); read(w[i]); read(c[i]); addedge(u[i] , v[i] , w[i]); addedge(v[i] , u[i] , w[i]); } dijkstra(); printf("%d\n" , dist[n]); tot = 1; for (int i = 1; i <= n; i++) head[i] = 0; for (int i = 1; i <= m; i++) { if (dist[u[i]] + w[i] == dist[v[i]]) addedgeF(u[i] , v[i] , c[i]); if (dist[v[i]] + w[i] == dist[u[i]]) addedgeF(v[i] , u[i] , c[i]); } int ans = 0; while (bfs()) { while (int flow = dinic(1 , inf)) ans += flow; } printf("%d\n" , ans); return 0; }