Ikki's Story I - Road Reconstruction
题意:有N个顶点和M条边N, M (N ≤ 500, M ≤ 5,000) ,试图改变图中的一条边使得从0到N-1的流量增加;问这样的边有几条?
思路:刚最大流入门,之后一看就觉得满流的边就是答案。。真是太天真了。之后看了题解,发现满流只是前提(即使满流是几次残量的叠加也是一样),还有一个条件是,该路径的最大流量只受该边影响;即可以从S和T遍历到该边的两个端点,这就是为什么之后还要dfs给点涂色的原因;涂色前要对残余网络中输入的边(反向边不管)标记重建图;
// 125ms #include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> #include<stack> #include<set> using namespace std; #define rep0(i,l,r) for(int i = (l);i < (r);i++) #define rep1(i,l,r) for(int i = (l);i <= (r);i++) #define rep_0(i,r,l) for(int i = (r);i > (l);i--) #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) #define MS0(a) memset(a,0,sizeof(a)) #define MS1(a) memset(a,-1,sizeof(a)) #define inf 0x3f3f3f3f #define pb push_back #define MK make_pair typedef pair<int,int> PII; #define A first #define B second template<typename T> void read1(T &m) { T x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} m = x*f; } template<typename T> void read2(T &a,T &b){read1(a);read1(b);} template<typename T> void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);} template<typename T> void out(T a) { if(a>9) out(a/10); putchar(a%10+'0'); } const int M = 5050; const int N = 550; int head[M<<1],tot; struct edge{ int from,to,cap,flow,Next; }e[M<<1]; void ins(int u,int v,int cap,int flow) { e[tot].Next = head[u]; e[tot].from = u;//为了t->s时由v推到u; e[tot].to = v; e[tot].cap = cap; e[tot].flow = flow; head[u] = tot++; } queue<int> q; vector<int> full; int p[N];//记录路径中边的标号 int a[N];//起点到i的可改进量 void Edmonds_Karp(int s,int t) { for(;;){ MS0(a); while(!q.empty()) q.pop(); a[s] = inf; q.push(s); while(!q.empty()){ int u = q.front();q.pop(); for(int id = head[u];~id;id = e[id].Next){ int v = e[id].to,c = e[id].cap,f = e[id].flow; if(!a[v] && c > f){ p[v] = id; a[v] = min(a[u],c - f);// ** 递推到a[v] q.push(v); } } if(a[t]) break; } if(!a[t]) break; for(int u = t;u != s;u = e[p[u]].from){ e[p[u]].flow += a[t]; e[p[u]^1].flow -= a[t]; if(e[p[u]].flow == e[p[u]].cap) full.pb(p[u]); } } } int color[N],V; void DFS(int u,int index) { if(~color[u]) return ; color[u] = index; for(int id = head[u];~id;id = e[id].Next){ if(id&1 || e[id].flow == e[id].cap) continue;//只在原边中找,不看反向边; DFS(e[id].to,index); } } int solve() { MS1(color); DFS(0,0);DFS(V-1,1); int ans = 0; rep0(i,0,full.size()){ int u = e[full[i]].from, v = e[full[i]].to; if(color[u] == 0 && color[v] == 1){ ans++; //out(u);putchar(' ');out(v);puts("bug"); } } return ans; } int main() { int n,E,kase = 1; read2(V,E); MS1(head);tot = 0; rep0(i,0,E){ int u,v,w; read3(u,v,w); ins(u,v,w,0);ins(v,u,0,0); } Edmonds_Karp(0,V-1); out(solve()); puts(""); return 0; }