Bzoj1797

Solution

先跑一边 Dinic,搞出残余网络。

可行边

一条边 $(x,y)$ 是可行边的充要条件为:

  • 满流
  • 在残余网络中找不到 $x->y$ 的路径

在代码中表现为 $x$ 和 $y$ 不在同一个强连通分量中。

必经边

在可行边的基础上,其多加的充要条件为

  • $x$ 和原点在一个强连通分量中,$y$ 和汇点在一个强连通分量中。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#include<bits/stdc++.h>
#define maxn 100005
#define int long long
#define put() putchar('\n')
using namespace std;
inline void read(int &x){
int f=1;x=0;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
x*=f;
}
const int inf=1e18;
int n,m,s,t;
int head=1,h[maxn];
struct yyy{
int to,z,w,u;
inline void add(int x,int y,int val){
to=y;z=h[x];w=val;h[x]=head;u=x;
}
}a[maxn*2];
inline void ins(int x,int y,int z){
a[++head].add(x,y,z);
a[++head].add(y,x,0);
}
namespace Dinic{
queue<int>q;
int deep[10005],now[maxn];
inline bool bfs(void) {
int i,x;
memset(deep,-1,sizeof(deep));
while (!q.empty()) q.pop();
q.push(s);deep[s]=1;
while (!q.empty()) {
x=q.front();q.pop();now[x]=h[x];
for (i=h[x];i;i=a[i].z)
if (deep[a[i].to]==-1&&a[i].w) {
deep[a[i].to]=deep[x]+1;
q.push(a[i].to);
}
}
return deep[t]!=-1;
}
inline int dfs(int x,int in){
if (x==t||!in) return in;
int i,rest=in,sum;
for (i=now[x];i&&rest;i=a[i].z){
now[x]=i;
if (deep[a[i].to]==deep[x]+1&&a[i].w) {
sum=dfs(a[i].to,min(rest,a[i].w));
rest-=sum;a[i].w-=sum;a[i^1].w+=sum;
if (!sum) deep[a[i].to]=0;
}
}
return in-rest;
}
inline int Dinic(void){
int ans=0;
while (bfs()) ans+=dfs(s,inf);
return ans;
}
}
int dfn[maxn],low[maxn],stac[maxn],tot,vis[maxn],scc[maxn],sccnum,times;
inline void tarjan(int x) {
int i;
dfn[x]=low[x]=++times;vis[x]=1;stac[++tot]=x;
for (i=h[x];i;i=a[i].z) {
if (!a[i].w) continue;
if (!dfn[a[i].to]) tarjan(a[i].to),low[x]=min(low[x],low[a[i].to]);
else if (vis[a[i].to]) low[x]=min(low[x],dfn[a[i].to]);
}
if (dfn[x]==low[x]) {
++sccnum;
while (1) {
vis[stac[tot]]=0;
scc[stac[tot]]=sccnum;
if (stac[tot--]==x) break;
}
}
}
signed main(void){
int i,x,y,z,j;
read(n);read(m);read(s);read(t);
for (i=1;i<=m;i++) {
read(x);read(y);read(z);
ins(x,y,z);
}
Dinic::Dinic();
for (i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
for (i=2;i<=m*2;i+=2) {
x=a[i].u;y=a[i].to;
if (a[i].w==0&&scc[x]!=scc[y]) {
printf("1 ");
if (scc[x]==scc[s]&&scc[y]==scc[t]) printf("1\n");
else printf("0\n");
}
else printf("0 0\n");
}
return 0;
}