【BZOJ 1797】 [Ahoi2009]Mincut 最小割

1797: [Ahoi2009]Mincut 最小割

Time Limit: 10 Sec  Memory Limit: 162 MB

Submit: 1244  Solved: 512

[Submit][Status][Discuss]

Description

A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路。设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci。现在B国想找出一个路径切断方案,使中转站s不能到达中转站t,并且切断路径的代价之和最小。 小可可一眼就看出,这是一个求最小割的问题。但爱思考的小可可并不局限于此。现在他对每条单向道路提出两个问题: 问题一:是否存在一个最小代价路径切断方案,其中该道路被切断? 问题二:是否对任何一个最小代价路径切断方案,都有该道路被切断?
现在请你回答这两个问题。

Input

第一行有4个正整数,依次为N,M,s和t。第2行到第(M+1)行每行3个正 整数v,u,c表示v中转站到u中转站之间有单向道路相连,单向道路的起点是v, 终点是u,切断它的代价是c(1≤c≤100000)。 注意:两个中转站之间可能有多条道路直接相连。 同一行相邻两数之间可能有一个或多个空格。

Output

对每条单向边,按输入顺序,依次输出一行,包含两个非0即1的整数,分 别表示对问题一和问题二的回答(其中输出1表示是,输出0表示否)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。

Sample Input

6 7 1 6

1 2 3

1 3 2

2 4 4

2 5 1

3 5 5

4 6 2

5 6 3

Sample Output

1 0

1 0

0 0

1 0

0 0

1 0

1 0

HINT

设第(i+1)行输入的边为i号边,那么{1,2},{6,7},{2,4,6}是仅有的三个最小代价切割方案。它们的并是{1,2,4,6,7},交是 。

【数据规模和约定】

测试数据规模如下表所示

数据编号 N M 数据编号 N M

1 10 50 6 1000 20000

2 20 200 7 1000 40000

3 200 2000 8 2000 50000

4 200 2000 9 3000 60000

5 1000 20000 10 4000 60000

Source

Day1

求最小割的可行边和必须边。

最小割:

最小割是割掉几条边,使得s和t不连通,并且割掉边的流量之和最小。且最小割等于最大流。

现在来考虑本题的要求。

把每个边看成粗细不同的水管,管子的粗细表示流量的大小,那么一条路径上的最大流量就是由最细的管子决定的。

因此这个最细的管子是满流的。

感性的想,要用最小的代价使水无法从s流到t,把这些最细的管子割掉就好了。

因此可行边和必须边一定是满流的。

先看可行边:

如果割掉这条边,还能从这条边的from到达to,这样割一点意义都没有。所以可行边被割掉之后,(在残量网络中)一定不能从他的from到达to。

再看必须边:

如果在残量网络中,s能到达这条边的from,这条边的to能到达t,说明这条边是他所在的路径上流量最小的边(唯一的),那么一定要割掉这条边。

因此这道题我们只要在残量网络中跑一边tarjan(因为有反向边,所以有环),根据上述条件判断对应点是否在同一个强连通分量中即可。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#define M 1000+5
#define inf 0x3f3f3f3f
#include <stack>
using namespace std;
stack<int> S;
int tot=1,scc_cnt,s,t,h[M],low[M],dfs_clock,dfn[M];
int scc[M],vt[M],v[M],d[M],cur[M],n,m;
struct edge
{
	int from,to,cap,flow,ne;
}E[200005];
void Addedge(int from,int to,int cap)
{
	E[++tot]=(edge){from,to,cap,0,h[from]};
	h[from]=tot;
	E[++tot]=(edge){to,from,0,0,h[to]};
	h[to]=tot;
}
bool bfs()
{
	queue<int> q;
	for (int i=1;i<=n;i++)
		v[i]=0;
	v[s]=1;
	d[s]=0;
	q.push(s);
	while (!q.empty())
	{
		int x=q.front();
		q.pop();
		for (int i=h[x];i;i=E[i].ne)
		{
			edge e=E[i];
			if (!v[e.to]&&e.cap>e.flow)
			{
				v[e.to]=1;
				d[e.to]=d[x]+1;
				q.push(e.to);
			}
		}
	}
	return v[t];
}
int dfs(int x,int a)
{
	if (x==t||!a) return a;
	int flow=0;
	for (int &i=cur[x];i;i=E[i].ne)
	{
		edge &e=E[i];
		if (d[e.to]!=d[x]+1) continue;
		int f=dfs(e.to,min(a,e.cap-e.flow));
		if (f)
		{
			a-=f;
			e.flow+=f;
			E[i^1].flow-=f;
			flow+=f;
			if (!a) break;
		}
	}
	return flow;
}
void dinic()
{
	while (bfs())
	{
		for (int i=1;i<=n;i++)
			cur[i]=h[i];
		dfs(s,inf);
	}
}
void tarjan(int x)
{
	dfn[x]=low[x]=++dfs_clock;
	S.push(x);
	for (int i=h[x];i;i=E[i].ne)
	{
		edge e=E[i];
		if (e.cap-e.flow<=0) continue;
		if (!dfn[e.to])
		{
			tarjan(e.to);
			low[x]=min(low[x],low[e.to]);
		}
		else
			if (!scc[e.to])
				low[x]=min(low[x],dfn[e.to]);
	}
	if (dfn[x]==low[x])
	{
		scc_cnt++;
		while (!S.empty())
		{
			int now=S.top();
			S.pop();
			scc[now]=scc_cnt;
			if (now==x)
				break;
		}
	}
}
int main()
{
        scanf("%d%d%d%d",&n,&m,&s,&t);
	for (int i=1;i<=m;i++)
	{
		int x,y,c;
		scanf("%d%d%d",&x,&y,&c);
		Addedge(x,y,c);
	}
	dinic();
	for (int i=1;i<=n;i++)
		if (!dfn[i])
			tarjan(i);
	for (int i=2;i<=tot;i+=2)
	{
		edge e=E[i];
		if (e.cap==e.flow&&scc[e.to]!=scc[e.from])
			printf("1");
		else
			printf("0");
		if (e.cap==e.flow&&scc[e.from]==scc[s]&&scc[e.to]==scc[t])
			printf(" 1\n");
		else
			printf(" 0\n");
	}
	return 0;
}

感悟:

1.TLE是点数看错,数组开小

时间: 2024-10-03 13:45:15

【BZOJ 1797】 [Ahoi2009]Mincut 最小割的相关文章

BZOJ 1797: [Ahoi2009]Mincut 最小割( 网络流 )

先跑网络流, 然后在残余网络tarjan缩点. 考虑一条边(u,v): 当且仅当scc[u] != scc[v], (u,v)可能出现在最小割中...然而我并不会证明 当且仅当scc[u] = scc[S] && scc[v] == scc[T], (u, v) 必定出现在最小割中. 这个很好脑补, 假如这条边不是满流, 那么S-T就存在增广路了.. ----------------------------------------------------------------------

bzoj 1797: [Ahoi2009]Mincut 最小割

求最小割的可行边与必须边,先求一遍最大流,然后在残量网络上求强连通分量,对于可行边 起始点与结束点要在不同的强连通分量里,对于必须边 起始点要与S在一个SCC里 结束点要与T在一个SCC里. 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<queue> 7 #incl

bzoj 1797: [Ahoi2009]Mincut 最小割【tarjan+最小割】

先跑一遍最大流,然后对残量网络(即所有没有满流的边)进行tarjan缩点. 能成为最小割的边一定满流:因为最小割不可能割一半的边: 连接s.t所在联通块的满流边一定在最小割里:如果不割掉这条边的话,就能再次从s到t增广 连接两个不同联通块的满流边可能在最小割里:新图(即缩点后只有满流边的图)的任意一条s.t割都是最小割,所以可以任取割的方案 #include<iostream> #include<cstdio> #include<cstring> #include<

[bzoj1797] [Ahoi2009]Mincut 最小割

问最小割中可能成为割边和一定会成为割边的边有哪些. 膜了半天各路题解. 比较详细的解释: http://blog.csdn.net/horizon_smz/article/details/50889806 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int maxn=4023,m

【最小割】【Dinic】【强联通分量缩点】bzoj1797 [Ahoi2009]Mincut 最小割

结论: 满足条件一:当一条边的起点和终点不在 残量网络的 一个强联通分量中.且满流. 满足条件二:当一条边的起点和终点分别在 S 和 T 的强联通分量中.且满流.. 网上题解很多的. 1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 #define IN

【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点

1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1685  Solved: 724[Submit][Status][Discuss] Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案

HYSBZ 1797 Mincut 最小割

Descrption A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案,使中转站s不能到达中转站t,并且切断路径的代价之和最小. 小可可一眼就看出,这是一个求最小割的问题.但爱思考的小可可并不局限于此.现在他对每条单向道路提出两个问题: 问题一:是否存在一个最小代价路径切断方案,其中该道路被切断? 问题二:

bzoj 1497 最大获利 - 最小割

新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU集团旗下的CS&T通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究.站址勘测.最优化等项目.在前期市场调查和站址勘测之后,公司得到了一共N个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第i个通讯中转站需要的成本为Pi(1≤i≤N).另外公司调查得出了所有期望中的

[BZOJ 2127] happiness 【最小割】

题目链接:BZOJ - 2127 题目分析 首先,每个人要么学文科,要么学理科,所以可以想到是一个最小割模型. 我们就确定一个人如果和 S 相连就是学文,如果和 T 相连就是学理. 那么我们再来确定建图.首先使用最小割,就是先加上所有可能获得的权值,再减去最小割(即不能获得的权值). 如果一个人学理,就要割掉与 S 相连的边,那么就是要割掉学文的收益.于是,对于每个点,从 S 向它连边,权值为它学文的收益. 同理,对于每个点,从它向 T 连边,权值为它学理的收益. 对于两个相邻的人,他们有同时学