1. 程式人生 > >USACO 4.4 追查壞牛奶

USACO 4.4 追查壞牛奶

get void 說明 十分 ans using 每次 amp pop

好題呀quq

第一問根據最大流最小割定理,求出最大流就是最小割的值

第二問就十分麻煩了,USACO還有一個加強版:求割邊的割集,這就比較棘手了

有一個比較投機取巧的方法:將所有的邊權乘以一個大質數並加一,此時的答案ans與原來的答案pre相比,有如下關系

ans = temp * mod + k

k即為最小割的邊數

但這樣的方法是過不去USACO的,我們得從最大流的本質去考慮

考慮到:對於一個割C(S,T),所有從S到T的邊必然滿流(否則殘余網絡上還有增廣路,可以繼續更新最大流)所以滿流的邊**可能**成為割邊,但不一定全都是(反例參照題目樣例) 但是,如果一條邊是割邊,割掉這條邊後,原圖的流量一定減去它的流量(如果不是這樣的話,說明可以用其他的邊代替這個邊,此邊就沒有必要割了)

所以,我們選出圖中所有滿流邊,每次試著去割去一條,看其是否是割邊(依照上文的方法)即可

這裏給出第一種方法的代碼,第二種方法調好後我會馬上上發

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
#define int long long 
const int maxn = 10005;
const int maxm = 2e5 + 5
; const int inf = 999999999; const int mod = 1007; inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < 0 || ch > 9) { if(ch == -) op = -1; ch = getchar(); } while(ch >= 0 && ch <= 9) { (ans *= 10) += ch - 0; ch
= getchar(); } return ans * op; } struct egde { int to,cost,next,other; }e[maxm]; int fir[maxn],alloc; void adde(int u,int v,int w) { e[++alloc].next = fir[u]; fir[u] = alloc; e[alloc].to = v; e[alloc].cost = w * mod + 1; e[alloc].other = alloc + 1; swap(u,v); e[++alloc].next = fir[u]; fir[u] = alloc; e[alloc].to = v; e[alloc].cost = 0; e[alloc].other = alloc - 1; } int n,m,s,t; int cnt,ans; bool vis[maxn]; int dep[maxn]; bool bfs(int s,int t) { memset(dep,0,sizeof(dep)); queue<int> q; dep[s] = 1; q.push(s); while(q.size()) { int u = q.front(); q.pop(); for(int i = fir[u];i;i = e[i].next) { int v = e[i].to,c = e[i].cost; if(c > 0 && dep[v] == 0 && vis[i] == 0) { dep[v] = dep[u] + 1; q.push(v); } } } //for(int i = 1;i <= n;i++) printf("%d %d\n",i,dep[i]); if(dep[t]) return 1; else return 0; } int find(int u,int f)//在u點,要解決值為f的流量 { //printf("%d %d\n",u,f); if(u == t) return f; int curflow = 0,t = 0; for(int i = fir[u];i;i = e[i].next) { int v = e[i].to,c = e[i].cost; if(c > 0 && dep[v] == dep[u] + 1 && curflow < f && vis[i] == 0) { t = find(v,min(c,f - curflow)); curflow += t; e[i].cost -= t; e[e[i].other].cost += t; } } return curflow; } main() { n = read(),m = read(); for(int i = 1;i <= m;i++) { int u = read(),v = read(),w = read(); adde(u,v,w); } s = 1,t = n; while(bfs(s,t)) ans += find(s,inf); printf("%d ",ans / mod); printf("%d",ans % mod); }

USACO 4.4 追查壞牛奶