先跑一遍最大流 然后在残余网络里面跑强连通 跑完过后对于每一条满流边的两个端点u, v
检验他们所在的强连通分量
若SCC[u] != SCC[v] 则这条边至少存在于一个最小割方案中
若SCC[u] != SCC[v] 并且 SCC[u] == SCC[S] && SCC[v] == SCC[T] 那么这一条边一定在任何一个最小割方案中
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#define SF scanf
#define PF printf
using namespace std;
typedef long long LL;
const int MAXN = 4000;
const int MAXM = 60000;
const int INF = 0x3f3f3f3f;
int n, m, S, T;
int dfn[MAXN+10], low[MAXN+10], dcnt, scc, SCC[MAXN+10];
int sta[MAXN+10], top;
int val[MAXM+10];
struct Node {
int u, v, c, next, id;
};
struct ISAP {
int gap[MAXN+10], d[MAXN+10];
int adj[MAXN+10], ecnt;
Node Edge[MAXM*2+10];
int n, s, t;
void init() {
memset(adj, -1, sizeof(adj));
}
void addedge(int u, int v, int c, int id) {
Node &e = Edge[ecnt];
e.v = v; e.u = u; e.c = c; e.id = id;
e.next = adj[u]; adj[u] = ecnt++;
}
void add(int u, int v, int c, int id) {
addedge(u, v, c, id);
addedge(v, u, 0, id);
}
void init_dis() {
queue <int> q;
memset(d, 0, sizeof(d));
memset(gap, 0, sizeof(gap));
q.push(t);
while(!q.empty()) {
int u = q.front(); q.pop();
gap[d[u]]++;
for(int i = adj[u]; ~i; i = Edge[i].next) {
int v = Edge[i].v;
if(!d[v] && v != t) d[v] = d[u] + 1, q.push(v);
}
}
}
int aug(int u, int inc) {
int Inc = 0, mindis = n-1;
if(u == t) return inc;
for(int i = adj[u]; ~i; i = Edge[i].next) {
Node &e = Edge[i];
int v = e.v, c = e.c;
if(c) {
if(d[v] == d[u] - 1) {
int del = min(c, inc - Inc);
del = aug(v, del);
Inc += del;
Edge[i].c -= del;
Edge[i^1].c += del;
if(d[s] >= n) return Inc;
if(inc == Inc) return inc;
}
mindis = min(mindis, d[v]);
}
}
if(!Inc) {
gap[d[u]]--;
if(gap[d[u]] == 0) d[s] = n;
d[u] = mindis + 1;
gap[d[u]]++;
}
return Inc;
}
int Maxflow(int _s, int _t, int _n) {
s = _s; t = _t; n = _n;
int ret = 0;
init_dis();
while(d[s] < n) ret += aug(s, INF);
return ret;
}
void dfs(int u) {
low[u] = dfn[u] = ++dcnt;
sta[++top] = u;
for(int i = adj[u]; ~i; i = Edge[i].next) {
Node &e = Edge[i];
int v = e.v, c = e.c;
if(!c) continue ;
if(!dfn[v]) {
dfs(v); low[u] = min(low[v], low[u]);
}
else if(!SCC[v]) low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u]) {
int x;
scc++;
do {
x = sta[top--];
SCC[x] = scc;
} while(x != u);
}
}
void build() {
for(int u = 1; u <= n; u++)
for(int i = adj[u]; ~i; i = Edge[i].next) {
Node &e = Edge[i];
int v = e.v, c = e.c;
if((i & 1) == 0 && c == 0) {
if(SCC[u] != SCC[v]) {
if(SCC[u] == SCC[S] && SCC[v] == SCC[T])
val[e.id] = 2;
else val[e.id] = 1;
}
}
}
}
} sap;
void find_scc() {
for(int i = 1; i <= n; i++) if(!dfn[i]) sap.dfs(i);
sap.build();
}
int main() {
sap.init();
SF("%d%d%d%d", &n, &m, &S, &T);
for(int i = 1; i <= m; i++) {
int u, v, c;
SF("%d%d%d", &u, &v, &c);
sap.add(u, v, c, i);
}
sap.Maxflow(S, T, n);
find_scc();
for(int i = 1; i <= m; i++)
if(val[i] == 2) puts("1 1");
else if(val[i] == 1) puts("1 0");
else puts("0 0");
}