考察:最小割的真正含义
我们知道最大流在意义上与最小割完全不同
但是最大流在数值上与最小割一样
本题也就是考察了在最大流上跑最小割的含义。
如何断定一条边被割断:反向边流量为w原边流量为0
这说明水流全部从这里流走了,也就是最小割。
看问题:
“问题一:是否存在一个最小代价路径切断方案,其中该道路被切断? 问题二:是否对任何一个最小代价路径切断方案,都有该道路被切断? 现在请你回答这两个问题。”
请冷静思考:
这现在的参量网路是一张类分层图。
只要把割断的边无视,那么这就是几块。
而且这也就成了混合图
我们考虑强联通关系。
第一S与T一定不在一起,否则图并没有割断。
其次当一条边(W=0):U,V的U,V不在一起,那么他们一定可以被选择在一条最小割上
因为割断它图并没有联通。
对于问题二,只要U和S在一起V和T在一起那么说明他们必须被割,否则图永远联通。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+1000;
const int INF=1e9+7;
inline void read(int &x){
x=0;
int 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();
}
x*=f;
}
struct Front_star{
int u,v,w,nxt;
}e[N*2];
int cnt=1;
int first[N]={};
void addedge(int u,int v,int w){
cnt++;
e[cnt].u=u;
e[cnt].v=v;
e[cnt].w=w;
e[cnt].nxt=first[u];
first[u]=cnt;
}
void add(int u,int v,int w){
addedge(u,v,w);
addedge(v,u,0);
}
int S;
int T;
int n,m;
int d[N]={};
queue<int> q;
bool BFS(){
for(int i=0;i<=n;i++)d[i]=-1;
d[S]=1;
q.push(S);
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=first[x];i;i=e[i].nxt){
int v=e[i].v;
if(e[i].w&&d[v]==-1){
d[v]=d[x]+1;
q.push(v);
}
}
}
return d[T]!=-1;
}
int dfs(int st,int ed,int nowdat){
if(st==ed){
return nowdat;
}
int dat=0;
for(int i=first[st];i;i=e[i].nxt){
int v=e[i].v;
if(e[i].w&&d[v]==d[st]+1){
int now=min(nowdat-dat,e[i].w);
now=dfs(v,ed,now);
e[i].w-=now;
e[i^1].w+=now;
dat+=now;
if(nowdat==dat){
return dat;
}
}
}
if(!dat){
d[st]=-2;
}
return dat;
}
int Dinic(){
int ret=0;
while(BFS()){
ret+=dfs(S,T,INF);
}
return ret;
}
//
int dfn[N]={};
int low[N]={};
int color[N]={};
int vis[N]={};
int scc=0;
int tot=0;
stack<int> St;
void tarjan(int u){
vis[u]=1;
St.push(u);
tot++;
dfn[u]=tot;
low[u]=tot;
for(int i=first[u];i;i=e[i].nxt){
int v=e[i].v;
if(e[i].w){
if(!dfn[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else{
if(vis[v]){
low[u]=min(low[u],dfn[v]);
}
}
}
}
if(low[u]==dfn[u]){
int x;
scc++;
do{
x=St.top();
vis[x]=0;
color[x]=scc;
St.pop();
}while(x!=u);
}
}
int main(){
read(n);
read(m);
read(S);
read(T);
for(int i=1;i<=m;i++){
int u,v,w;
read(u);
read(v);
read(w);
add(u,v,w);
}
Dinic();
for(int i=1;i<=n;i++){
if(!dfn[i]){
tarjan(i);
}
}
for(int i=2;i<=cnt;i+=2){
if(e[i].w)puts("0 0");
else{
if(color[e[i].u]!=color[e[i].v])printf("1 ");
else printf("0 ");
if(color[S]==color[e[i].u]&&color[T]==color[e[i].v])puts("1");
else puts("0");
}
}
}