分析
主要考察最小割的性质。我们发现如果一条边是可行边,那么一定要满足以下性质。
满流,没有第二条增广路 。考虑证明,如果没有满流,那么我们完全没必要割去这条边。如果有,那么证明这个路径还可以继续增广,不满足最小割的定义。
那么如果一条边是必须边。满流,直接链接
所在集合。这里考虑最小割的定义。
那么我们只需要通过 把
求出来就行了。数组开的很奔放,不用太在意。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 4e5 + 100,inf = 0x3f3f3f3f;
int read() {
int x = 0;char ch = getchar();
while(!isdigit(ch)) {ch = getchar();}
while(isdigit(ch)) {x = x * 10 + ch - '0';ch = getchar();}
return x;
}
struct Edge{int to,nxt,from,cap;}e[N<<1];
int head[N],dis[N],cur[N],dfn[N],low[N],scc[N],vis[N],st[N],top,ecnt = 1;
int n,m,S,T;
queue<int> Q;
bool Bfs(int s,int t) {
memset(dis,0,sizeof(dis));dis[s] = 1;while(Q.size()) Q.pop();
Q.push(s);
while(!Q.empty()) {
int x = Q.front();Q.pop();
for(int i = head[x];i;i = e[i].nxt) {
int y = e[i].to;if(!dis[y] && e[i].cap > 0) {
dis[y] = dis[x] + 1;if(y == t) return true;
Q.push(y);
}
}
}
return false;
}
int Dfs(int x,int a,int t) {
if(x == t || a == 0) return a;
int flow = 0,f = 0;
for(int i = cur[x];i;i = e[i].nxt) {
int y = e[i].to;cur[x] = i;
if((dis[y] == dis[x] + 1) && ((f = Dfs(y,min(a,e[i].cap),t)) > 0)) {
e[i].cap -= f;e[i^1].cap += f;flow += f;a -= f;if(!a) break;
}
}
return flow;
}
void add(int x,int y,int cap) {
e[++ecnt].to = y;e[ecnt].from = x;e[ecnt].cap = cap;e[ecnt].nxt = head[x];head[x] = ecnt;
e[++ecnt].to = x;e[ecnt].from = 0;e[ecnt].cap = 0 ;e[ecnt].nxt = head[y];head[y] = ecnt;
}
int Scc,Tim;
void tarjan(int x) {
dfn[x] = low[x] = ++Tim;vis[x] = 1;st[++top] = x;
for(int i = head[x];i;i = e[i].nxt) {
int y = e[i].to;if(!e[i].cap) continue;
if(!dfn[y]) {
tarjan(y);low[x] = min(low[x],low[y]);
}
else if(vis[y]) low[x] = min(low[x],dfn[y]);
}
if(dfn[x] == low[x]) {
Scc++;scc[x] = Scc;
while(st[top] != x) {
scc[st[top]] = Scc;vis[st[top]] = 0;top--;
}
top--;vis[x] = 0;
}
}
int main() {
n = read();m = read();S = read();T = read();
for(int i = 1;i <= m;i++) {
int x = read(),y = read(),c = read();add(x,y,c);
}
int Maxflow = 0;
while(Bfs(S,T)) {
for(int i = 1;i <= n;i++) cur[i] = head[i];Maxflow += Dfs(S,inf,T);
}
for(int i = 1;i <= n;i++) {if(!dfn[i]) tarjan(i);}
for(int i = 2;i <= ecnt;i += 2) {
if(!e[i].cap) {
printf("%d %d\n",(scc[e[i].from] != scc[e[i].to]),((scc[e[i].from] == scc[S]) && (scc[e[i].to] == scc[T])) );
}
else printf("0 0 \n");
}
return 0;
}
京公网安备 11010502036488号