POJ3068 "Shortest" pair of paths
阿新 • • 發佈:2018-11-24
嘟嘟嘟
題目大意:一個有向圖,每一條邊有一個邊權,求從節點\(0\)到\(n - 1\)的兩條不經過同一條邊的路徑,並且邊權和最小。
費用流板子題。
發個部落格證明一下我寫了這題。
#include<cstdio> #include<iostream> #include<cmath> #include<algorithm> #include<cstring> #include<cstdlib> #include<cctype> #include<vector> #include<stack> #include<queue> using namespace std; #define enter puts("") #define space putchar(' ') #define Mem(a, x) memset(a, x, sizeof(a)) #define rg register typedef long long ll; typedef double db; const int INF = 0x3f3f3f3f; const db eps = 1e-8; const int maxn = 70; const int maxm = 1e4 + 5; inline ll read() { ll ans = 0; char ch = getchar(), last = ' '; while(!isdigit(ch)) last = ch, ch = getchar(); while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar(); if(last == '-') ans = -ans; return ans; } inline void write(ll x) { if(x < 0) x = -x, putchar('-'); if(x >= 10) write(x / 10); putchar(x % 10 + '0'); } int n, m, s, t; struct Edge { int nxt, from, to, cap, c; }e[maxm << 1]; int head[maxn], ecnt = -1; void addEdge(int x, int y, int w, int c) { e[++ecnt] = (Edge){head[x], x, y, w, c}; head[x] = ecnt; e[++ecnt] = (Edge){head[y], y, x, 0, -c}; head[y] = ecnt; } queue<int> q; bool in[maxn]; int dis[maxn], pre[maxn], flow[maxn]; bool spfa() { Mem(in, 0); Mem(dis, 0x3f); in[s] = 1; dis[s] = 0; flow[s] = INF; q.push(s); while(!q.empty()) { int now = q.front(); q.pop(); in[now] = 0; for(int i = head[now], v; i != -1; i = e[i].nxt) { v = e[i].to; if(e[i].cap && dis[now] + e[i].c < dis[v]) { dis[v] = dis[now] + e[i].c; pre[v] = i; flow[v] = min(flow[now], e[i].cap); if(!in[v]) in[v] = 1, q.push(v); } } } return dis[t] != INF; } int maxFlow = 0, minCost = 0; void update() { int x = t; while(x != s) { int i = pre[x]; e[i].cap -= flow[t]; e[i ^ 1].cap += flow[t]; x = e[i].from; } maxFlow += flow[t]; minCost += dis[t] * flow[t]; } void MCMF() { while(spfa()) update(); } void init() { Mem(head, -1); ecnt = -1; maxFlow = minCost = 0; } int main() { int T = 0; while(scanf("%d%d", &n, &m) != EOF && n && m) { init(); s = 0; t = n + 1; for(int i = 1; i <= m; ++i) { int x = read() + 1, y = read() + 1, c = read(); addEdge(x, y, 1, c); } addEdge(s, 1, 2, 0); addEdge(n, t, 2, 0); MCMF(); printf("Instance #%d: ", ++T); if(maxFlow < 2) puts("Not possible"); else write(minCost), enter; } return 0; }