【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点
1797: [Ahoi2009]Mincut 最小割
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 1685 Solved: 724
[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
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
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 M1 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
2015.4.16新加数据一组,可能会卡掉从前可以过的程序。
Source
Solution
首先,最小割-最大流定理,很显然想到最大流
那么问题在于对于各个边是否选择的情况的判断
考虑在求完最小割(最大流)的残余网络上进行处理,那么想到Tarjan+缩点
讨论后发现,如下判断即可:
对于问题1:
如果一条边的左右端点不在同一SCC中,那么为1,否则为0
对于问题2:
满足一条边的左右端点必须一个端点与s同SCC,另一个端点与t同SCC,此时为1,否则为0
当然还有一个特例,那就是这个边从未被割,那么很显然对于问题1和问题2同时为0
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
//quick read
#define maxn 4000+100
#define maxm (60000+100)*2
struct data{int from,to,next,cap;}edge[maxm];
int head[maxn],cnt=,cur[maxn];
void add(int u,int v,int w)
{cnt++;edge[cnt].to=v;edge[cnt].from=u;
edge[cnt].next=head[u];head[u]=cnt;edge[cnt].cap=w;}
void insert(int u,int v,int w){add(u,v,w);add(v,u,);}
//add edge
int n,m,s,t;int dis[maxn],q[maxn];
bool bfs()
{
for (int i=; i<=n; i++) dis[i]=-;
int he=,ta=; q[]=s; dis[s]=;
while (he<ta)
{
int now=q[he++];
for (int i=head[now]; i; i=edge[i].next)
if (dis[edge[i].to]==- && edge[i].cap)
dis[edge[i].to]=dis[now]+,q[ta++]=edge[i].to;
}
return dis[t]!=-;
}
int dfs(int loc,int low)
{
if (loc==t) return low;
int w,used=;
for (int i=cur[loc]; i; i=edge[i].next)
if (dis[edge[i].to]==dis[loc]+)
{
w=dfs(edge[i].to,min(low-used,edge[i].cap));
edge[i].cap-=w;edge[i^].cap+=w;
if (edge[i].cap) cur[loc]=i;
used+=w; if (used==low) return low;
}
if (!used) dis[loc]=-;
return used;
}
#define inf 0x7fffffff
int dinic()
{
int tmp=;
while (bfs())
{
for (int i=; i<=n; i++) cur[i]=head[i];
tmp+=dfs(s,inf);
}
return tmp;
}
//MaxFlow Dinic
int stack[maxn],st,qcnt,tot;
int dfn[maxn],loww[maxn],belong[maxn],num[maxn];bool visit[maxn];
void Tarjan(int x)
{
dfn[x]=loww[x]=++tot; stack[++st]=x; visit[x]=;
for (int i=head[x]; i; i=edge[i].next)
if (edge[i].cap)//根据题意,在Tarjan的时候需要进行此判断,否则会出问题
{
if (!dfn[edge[i].to])
{
Tarjan(edge[i].to);
if (loww[edge[i].to]<loww[x]) loww[x]=loww[edge[i].to];
}
else if(visit[edge[i].to] && dfn[edge[i].to]<loww[x])
loww[x]=dfn[edge[i].to];
}
if (dfn[x]==loww[x])
{
qcnt++;int u;
while (x!=u)
u=stack[st--],num[qcnt]++,
visit[u]=,belong[u]=qcnt;
}
}
//Tarjan SCC
int main()
{
n=read(),m=read(),s=read(),t=read();
for (int u,v,c,i=; i<=m; i++)
u=read(),v=read(),c=read(),insert(u,v,c);
int maxflow=dinic();
for (int i=; i<=n; i++)
if (!dfn[i]) Tarjan(i);
for (int ans1,ans2,u,v,i=; i<=cnt; i+=)
{
u=edge[i].from,v=edge[i].to;
if (edge[i].cap) ans1=,ans2=;
else
{
if (belong[u]!=belong[v])
ans1=; else ans1=;
if (belong[u]==belong[s] && belong[v]==belong[t])
ans2=; else ans2=;
}
printf("%d %d\n",ans1,ans2);
}
return ;
}
本来应该做的飞快,然而...自己脑残打错两个变量...坑了好久....SB错误毁一生啊!!
【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点的更多相关文章
- HYSBZ 1797 Mincut 最小割
Descrption A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站, ...
- bzoj1797: [Ahoi2009]Mincut 最小割(网络流,缩点)
传送门 首先肯定要跑一个最小割也就是最大流 然后我们把残量网络tarjan,用所有没有满流的边来缩点 一条边如果没有满流,那它就不可能被割了 一条边如果所属的两个强联通分量不同,它就可以被割 一条边如 ...
- [BZOJ 1797][AHOI2009]最小割(最小割关键边的判断)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1797 分析: 在残余网络中看: 对于第1问: 1.首先这个边必须是满流 2.其次这个边 ...
- BZOJ 1797: [Ahoi2009]Mincut 最小割
1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2076 Solved: 885[Submit] ...
- BZOJ 1797: [Ahoi2009]Mincut 最小割( 网络流 )
先跑网络流, 然后在残余网络tarjan缩点. 考虑一条边(u,v): 当且仅当scc[u] != scc[v], (u,v)可能出现在最小割中...然而我并不会证明 当且仅当scc[u] = scc ...
- 1797: [Ahoi2009]Mincut 最小割
1797: [Ahoi2009]Mincut 最小割 链接 分析: 题意为:问一条边是否可能存在于最小割中,是否一定存在于最小割中. 首先最小割的边一定是满流的边.且这条边点两个端点u.v中,至少一个 ...
- BZOJ_1797_[Ahoi2009]Mincut 最小割_最小割+tarjan
BZOJ_1797_[Ahoi2009]Mincut 最小割_最小割+tarjan Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤ ...
- bzoj1797: [Ahoi2009]Mincut 最小割(最小割+强联通tarjan)
1797: [Ahoi2009]Mincut 最小割 题目:传送门 题解: 感觉是一道肥肠好的题目. 第二问其实比第一问简单? 用残余网络跑强联通,流量大于0才访问. 那么如果两个点所属的联通分量分别 ...
- bzoj1797: [Ahoi2009]Mincut 最小割
最大流+tarjan.然后因为原来那样写如果图不连通的话就会出错,WA了很久. jcvb: 在残余网络上跑tarjan求出所有SCC,记id[u]为点u所在SCC的编号.显然有id[s]!=id[t] ...
随机推荐
- POJ 1847 Tram --set实现最短路SPFA
题意很好懂,但是不好下手.这里可以把每个点编个号(1-25),看做一个点,然后能够到达即为其两个点的编号之间有边,形成一幅图,然后求最短路的问题.并且pre数组记录前驱节点,print_path()方 ...
- AC日记——积木大赛 洛谷 P1969
题目描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前,没有任何积木(可以看成 ...
- LoadRunner 11 完整卸载
实现彻底删除LR的步骤 打开任务管理器,关闭所有LR相关的进程 请备份好所有LR脚本 进入控制面板-添加与删除,找到HP LoadRunner并点击删除按钮,若出现提示“shared DLLs”消息框 ...
- 本地不安装Oracle,plsql远程连接数据库
由于Oracle的庞大,有时候我们需要在只安装Oracle客户端如plsql.toad等的情况下去连接远程数据库,可是没有安装Oracle就没有一切的配置文件去支持.最后终于发现一个很有效的方法,Or ...
- 我为什么反对推荐新人编程C/C++语言入门?
虽然我接触编程以及计算机时间比较早,但是正式打算转入程序员这个行当差不多是大学第四年的事情 从03年接触计算机,07年开始接触计算机编程, 期间接触过的技术包括 缓冲区溢出(看高手写的shellcod ...
- C++中的运算符重载
首先思考以下几个问题: 1.什么是运算符重载? 2.为什么要重载运算符,它有什么用? 3.可以重载哪些运算符? 4.重载运算符有哪些规则? 一.基本概念 我们在程序中使用各种操作符,比如加(+).赋值 ...
- ASP.NET MVC Razor HtmlHelper扩展和自定义控件
先看示例代码: using System; using System.Collections.Generic; using System.Linq; using System.Web; using S ...
- 调用Oracle存储过程并获取out参数值
原文: http://tech.it168.com/oldarticle/2006-04-02/200604021512359.shtml http://www.cnblogs.com/m-cnblo ...
- 学习node.js 第4篇 建立一个最小的web聊天系统
我们生活在一个实时的世界里,有什么比聊天更加实时吗?那就让我们先写一个基于TCP 的聊天服务器吧,并且支持Telnet 连接.这很容易,而且能够完全用Node来编写.首先,我们需要在Node 中包含T ...
- [PY]进制转换
ord('j') 将字符转换为10进制 int(ord(‘j’),16) 把10进制转化为16进制 http://www.108kb.com/python/item/43662.htm http:// ...