最小截断[AHOI2009]
【题目描述】
宇宙旅行总是出现一些意想不到的问题,这次小可可所驾驶的宇宙飞船所停的空间站发生了故障,这个宇宙空间站非常大,它由N个子站组成,子站之间有M条单向通道,假设其中第i(1<=i<=M)条单向通道连接了xi,yi两个中转站,那么xi子站可以通过这个通道到达yi子站,如果截断这条通道,需要代价ci。现在为了将故障的代价控制到最小,小可可必须想出一个截断方案,使a站不能到达b子站,并且截断的代价之和最小。我们称之为最小截断,小可可很快解决了这个故障,但是爱思考的小可可并不局限于此,为了今后更方便的解决同类故障,他考虑对每条单向通道:
1,是否存在一个最小代价路径截断方案,其中该通道被切断?
2,是否对任何一个最小代价路径切断方案,都有该通道被切断?
聪明的你能帮小可可解决他的疑问吗?
【输入格式】
第一行有4个整数,依次为N,M,a和b;
第二行到第(m+1)行每行3个正整数x,y,c表示x子站到y子站之间有单向通道相连,单向通道的起点是x终点是y,切断它的代价是c(1<=c<=10000);
两个子站之间可能有多条通道直接连接。
【输出格式】
对每一个单向通道,按输入的顺序,依次输出一行包含两个非0即1的整数,分别表示对问题一和问题二的回答(其中1表示是,0表示否)。每行两个整数之间用一个空格分隔开。
【样例输入】
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
【样例输出】
1 0
1 0
0 0
1 0
0 0
1 0
1 0
【提示】
100%的数据中,N<=4000,M<=60000
70%的数据中,N<=1000,M<=40000
40%的数据中,N<=200,M<=2000
【题解】
血帆海盗的进阶版,先贴结论XDDD:
最小割的必须边
一定在最小割中的边、扩大容量后能增大最大流的边, ① 满流;② 残余网络中S能到入点、出点能到T。 从S开始DFS、T开始反向DFS,标记到达的点,然后枚举满流边即可。
最小割的可行边
被某一种最小割的方案包含的边, ① 满流;② 删掉之后在残余网络中找不到u到v的路径。 在残余网络中tarjan求SCC,(u,v)两点在同一SCC中说明残余网络中存在u到v路径。
但是在这道题里求必须边好像不能用dfs,上面那个结论已经忘了是从哪里看的了= =,必须边的起点与S在同一个强联通分量里,终点与T在同一个强联通分量里。知道了结论之后就可以放心地跑了。
写一点理解:残余网络中不能形成强连通分量的只有满流边(或许还有没用到的边?但是那不会被统计答案),所以残余网络缩成DAG的每个s-t割都是原图中的一个最小割,这是可行性。而u、v分别和s、t同处一个强联通分量的边一旦边权增加就会产生增广路径,这恰好符合必须边的定义。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
queue<int> q;
stack<int> s;
const int sj=;
const int sm=;
int n,m,si,t,a1,a2,a3,e,h[sj],c[sj],dep[sj],dfn[sj],low[sj];
bool r[sj];
struct B
{
int ne,v,w,u;
}b[sm<<];
inline int read()
{
int jg=,jk=getchar()-'';
while(jk<||jk>) jk=getchar()-'';
while(jk>=&&jk<=) jg*=,jg+=jk,jk=getchar()-'';
return jg;
}
void add(int x,int y,int z)
{
b[e].u=x,b[e].v=y,b[e].w=z,b[e].ne=h[x],h[x]=e++;
b[e].u=y,b[e].v=x,b[e].w=,b[e].ne=h[y],h[y]=e++;
}
bool bfs(int x)
{
memset(dep,,sizeof(dep));
while(!q.empty()) q.pop();
dep[x]=,q.push(x);
while(!q.empty())
{
x=q.front(),q.pop();
for(int i=h[x];i!=-;i=b[i].ne)
if(!dep[b[i].v]&&b[i].w)
{
dep[b[i].v]=dep[x]+;
if(b[i].v==t) return ;
q.push(b[i].v);
}
}
return ;
}
int dfs(int x,int f)
{
if(x==t) return f;
int ret=,d;
for(int i=h[x];i!=-;i=b[i].ne)
if(dep[b[i].v]==dep[x]+&&b[i].w)
{
d=dfs(b[i].v,min(f,b[i].w));
ret+=d,f-=d;
b[i].w-=d,b[i^].w+=d;
if(!f) break;
}
if(!ret) dep[x]=-;
return ret;
}
void bj(int &x,int y)
{
x=x<y?x:y;
}
void tarjan(int x)
{
dfn[x]=low[x]=++a1,r[x]=,s.push(x);
for(int i=h[x];i!=-;i=b[i].ne)
{
if(!b[i].w) continue;
if(!dfn[b[i].v]) tarjan(b[i].v),bj(low[x],low[b[i].v]);
else if(r[b[i].v]) bj(low[x],dfn[b[i].v]);
}
if(low[x]==dfn[x])
{
a2++;
do
{
a3=s.top(),s.pop();
r[a3]=,c[a3]=a2;
}while(a3!=x);
}
}
int main()
{
memset(h,-,sizeof(h));
n=read(),m=read(),si=read(),t=read();
for(int i=;i<=m;i++)
{
a1=read(),a2=read(),a3=read();
add(a1,a2,a3);
}
while(bfs(si)) dfs(si,0x7fffffff);
a1=a2=a3=;
for(int i=;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=;i<e;i+=)
{
if(b[i].w) printf("0 0\n");
else
{
if(c[b[i].u]!=c[b[i].v])
{
if(c[b[i].v]==c[t]&&c[b[i].u]==c[si]) printf("1 1\n");
else printf("1 0\n");
}
else printf("0 0\n");
}
}
return ;
}
mincut
最小截断[AHOI2009]的更多相关文章
- gensim中word2vec
from gensim.models import Word2Vec Word2Vec(self, sentences=None, size=100, alpha=0.025, window=5, m ...
- BZOJ 1797: [Ahoi2009]Mincut 最小割
1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2076 Solved: 885[Submit] ...
- bzoj1797: [Ahoi2009]Mincut 最小割
最大流+tarjan.然后因为原来那样写如果图不连通的话就会出错,WA了很久. jcvb: 在残余网络上跑tarjan求出所有SCC,记id[u]为点u所在SCC的编号.显然有id[s]!=id[t] ...
- AHOI2009最小割
1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1072 Solved: 446[Submit] ...
- BZOJ 1797: [Ahoi2009]Mincut 最小割( 网络流 )
先跑网络流, 然后在残余网络tarjan缩点. 考虑一条边(u,v): 当且仅当scc[u] != scc[v], (u,v)可能出现在最小割中...然而我并不会证明 当且仅当scc[u] = scc ...
- BZOJ_1797_[Ahoi2009]Mincut 最小割_最小割+tarjan
BZOJ_1797_[Ahoi2009]Mincut 最小割_最小割+tarjan Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤ ...
- P4126 [AHOI2009]最小割
题目地址:P4126 [AHOI2009]最小割 最小割的可行边与必须边 首先求最大流,那么最小割的可行边与必须边都必须是满流. 可行边:在残量网络中不存在 \(x\) 到 \(y\) 的路径(强连通 ...
- 【BZOJ1797】[AHOI2009]最小割(网络流)
[BZOJ1797][AHOI2009]最小割(网络流) 题面 BZOJ 洛谷 题解 最小割的判定问题,这里就当做记结论吧.(源自\(lun\)的课件) 我们先跑一遍最小割,求出残量网络.然后把所有还 ...
- 1797: [Ahoi2009]Mincut 最小割
1797: [Ahoi2009]Mincut 最小割 链接 分析: 题意为:问一条边是否可能存在于最小割中,是否一定存在于最小割中. 首先最小割的边一定是满流的边.且这条边点两个端点u.v中,至少一个 ...
随机推荐
- [平衡树] mingap
时间限制: 1 Sec 内存限制: 128 MB提交: 18 解决: 9 题目描述 实现一种数据结构,维护以下两个操作: (1) I x :加入元素 x : (2) M :输出当前表中相差最小的两 ...
- XManager5连接CentOS7
XManager5连接CentOS6的方法已经行不通了,那么如何用XManager5连接CentOS7 从Xmanger官网博客得知: "Gnome in CentOS 7 tries to ...
- PHP判断字符串中是否含有中文
<?php $str = "测试中文"; echo $str; echo "<hr>"; //if (preg_match("/^[ ...
- PHP数组按引用传递
<?php /**PHP数组按引用传递**/ $arr = array( array('id' => 1, 'name' => 'name1'), array('id' => ...
- 学编程担心自己英语不好吗?(IT软件开发常用英语词汇)
发一份,我们导师的收集的常用词汇,与大家共享 欢迎加入Java学习交流裙六一六九五九四四四! S 欢迎加入Java学习交流裙 六一六 九五九 四四四!
- 基于邮件系统的远程实时监控系统的实现 Python版
人生苦短,我用Python~ 界内的Python宣传标语,对Python而言,这是种标榜,实际上,Python确实是当下最好用的开发语言之一. 在相继学习了C++/C#/Java之后,接触Python ...
- HTML DOM元素关系与操作
<html> <head><title>DOM元素关系与操作</title></head> <body> <!-- div ...
- android studio gradle 两种更新方法更新
android studio gradle 两种更新方法更新 第一种.Android studio更新 第一步:在你所在项目文件夹下:你项目根目录gradlewrappergradle-wrapper ...
- SQL SERVER查看索引使用情况
SELECT DISTINCT DB_NAME() AS N'db_name' , E.name AS N'schema_name' , OBJECT_NAME(a.object_id) AS N't ...
- 底层码农的Stanford梦 --- 从SCPD开始 [转]
转载自知乎: https://zhuanlan.zhihu.com/p/25010074 一开始让我写这篇文章的时候,我是拒绝的.毕竟,我不是Stanford毕业的,出来写文章介绍Stanford,难 ...