【bzoj1797】 Ahoi2009—Mincut 最小割

http://www.lydsy.com/JudgeOnline/problem.php?id=1797 (題目連接)php

題意

  求一條邊是否可能在一個最小割集中,以及這條邊是否必定在最小割集中。html

Solution

  DaD3zZ大爺ios

  跑完最大流之後,在殘餘網絡上跑tarjan求出全部SCC,記belong[u]爲點u所在SCC的編號。顯然有belong[s]!=belong[t](不然s到t有通路,能繼續增廣)。
  ①對於任意一條滿流邊(u,v),(u,v)可以出如今某個最小割集中,當且僅當belong[u]!=belong[v];
  ②對於任意一條滿流邊(u,v),(u,v)一定出如今最小割集中,當且僅當belong[u]==belong[s]且belong[v]==belong[t]。c++

細節

  我也不知道爲何犯了若干sb錯誤= =網絡

代碼

// bzoj1797
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#define LL long long
#define inf (1ll<<60)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std;

const int maxn=1000010;
int head[maxn],bel[maxn],low[maxn],dfn[maxn],st[maxn],id[maxn],n,m,S,T,top,scc,cnt=1;
struct edge {int from,to,next,w;}e[maxn];

namespace Dinic {
	int d[maxn];
	bool bfs() {
		memset(d,-1,sizeof(d));
		queue<int> q;q.push(S);d[S]=0;
		while (!q.empty()) {
			int x=q.front();q.pop();
			for (int i=head[x];i;i=e[i].next)
				if (e[i].w && d[e[i].to]<0) d[e[i].to]=d[x]+1,q.push(e[i].to);
		}
		return d[T]>0;
	}
	int dfs(int x,LL f) {
		if (x==T || f==0) return f;
		int w,used=0;
		for (int i=head[x];i;i=e[i].next) if (e[i].w && d[e[i].to]==d[x]+1) {
				w=dfs(e[i].to,min(1LL*e[i].w,f-used));
				used+=w,e[i].w-=w,e[i^1].w+=w;
				if (used==f) return used;
			}
		if (!used) d[x]=-1;
		return used;
	}
	void main() {
		while (bfs()) dfs(S,inf);
	}
}

void link(int u,int v,int w) {
	e[++cnt]=(edge){u,v,head[u],w};head[u]=cnt;
	e[++cnt]=(edge){v,u,head[v],0};head[v]=cnt;
}
void Tarjan(int x) {
	low[x]=dfn[x]=++cnt;
	st[++top]=x;
	for (int i=head[x];i;i=e[i].next) if (e[i].w) {
			if (!dfn[e[i].to]) {
				Tarjan(e[i].to);
				low[x]=min(low[x],low[e[i].to]);
			}
			else if (!bel[e[i].to]) low[x]=min(low[x],dfn[e[i].to]);
		}
	if (dfn[x]==low[x]) {
		scc++;
		for (;st[top]!=x;top--) bel[st[top]]=scc;
		bel[st[top--]]=scc;
	}
}
int main() {
	scanf("%d%d%d%d",&n,&m,&S,&T);
	for (int u,v,w,i=1;i<=m;i++) {
		scanf("%d%d%d",&u,&v,&w);
		id[i]=cnt+1;
		link(u,v,w);
	}
	Dinic::main();cnt=0;
	for (int i=1;i<=n;i++) if (!dfn[i]) Tarjan(i);
	for (int i=1;i<=m;i++) {
		int j=id[i];
		if (e[j].w!=0 || bel[e[j].from]==bel[e[j].to]) {puts("0 0");continue;}
		if (bel[e[j].from]==bel[S] && bel[e[j].to]==bel[T]) puts("1 1");
		else puts("1 0");
	}
	return 0;
}
相關文章
相關標籤/搜索