题目链接:https://cn.vjudge.net/contest/281961#problem/B

题目大意:给你n个城市,中间有一些中转站,然后给你终点,再给你l条轨道以及流量,问你增加哪几条轨道的流量可以使得流到终点的流量增加。

具体思路:首先分析一波,一开始想的是找割边,但是只是找出割边是不可以的。举个例子 : s->u->t,这样的话,假设这两条边都是满流,都可以当做割边,但是如果只是增加割边的流量的话,会受到其他边的流量的限制,最终流量还是不会增加的,所以,换一个思路,我们先跑一遍最大流,然后观察残余网络的情况,如果一条边的起点和终点对应的起点作为另一条边的终点以及终点对应另一条边的起点的话,依旧是如果增加当前这条边的流量的话,还是可以增加流量的,这样关键割边就找出来了。

AC代码:

 #include<iostream>
#include<stack>
#include<queue>
#include<iomanip>
#include<stdio.h>
#include<cstring>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
# define ll long long
const int maxn = 4e3+;
# define inf 0x3f3f3f3f
int st,ed;
int prev[maxn];
int head[maxn];
int line[maxn];
int vis1[maxn],vis2[maxn];
struct node
{
int fr;
int to;
int flow;
int nex;
} edge[maxn];
int num;
void init()
{
memset(head,-,sizeof(head));
memset(vis1,,sizeof(vis1));
memset(vis2,,sizeof(vis2));
num=;
}
void addedge(int fr,int to,int flow)
{
edge[num].to=to;
edge[num].fr=fr;
edge[num].flow=flow;
edge[num].nex=head[fr];
head[fr]=num++;
edge[num].to=fr;
edge[num].fr=to;
edge[num].flow=;
edge[num].nex=head[to];
head[to]=num++;
}
bool bfs()
{
memset(prev,-,sizeof(prev));
prev[st]=;
queue<int>q;
q.push(st);
while(!q.empty())
{
int top=q.front();
q.pop();
for(int i=head[top]; i!=-; i=edge[i].nex)
{
int temp=edge[i].to;
if(prev[temp]==-&&edge[i].flow>)
{
prev[temp]=prev[top]+;
q.push(temp);
}
}
}
return prev[ed]!=-;
}
int dfs(int u,int flow)
{
if(u==ed)
return flow;
int res=;
for(int i=head[u]; i!=-; i=edge[i].nex)
{
int t=edge[i].to;
if(prev[t]==(prev[u]+)&&edge[i].flow>)
{
int temp=dfs(t,min(flow,edge[i].flow));
edge[i].flow-=temp;
edge[i^].flow+=temp;
res+=temp;
flow-=temp;
if(flow==)
break;
}
}
if(res==)
prev[u]=-;
return res;
}
void dinic()
{
int ans=;
while(bfs())
{
ans+=dfs(st,inf);
}
}
void dfs1(int u)
{
vis1[u]=;
for(int i=head[u]; i!=-; i=edge[i].nex)
{
int v=edge[i].to;
if(!vis1[v]&&edge[i].flow)
dfs1(v);
}
}
void dfs2(int u)
{
vis2[u]=;
for(int i=head[u]; i!=-; i=edge[i].nex)
{
int v=edge[i].to;
if(!vis2[v]&&edge[i^].flow)
{
dfs2(v);
}
}
}
int main()
{
int n,m,l;
while(~scanf("%d",&n))
{
if(n==)
break;
init();
scanf("%d %d",&m,&l);
st=n+m+;
ed=;
int t1,t2,t3;
for(int i=; i<l; i++)
{
scanf("%d %d %d",&t1,&t2,&t3);
line[i]=num;
addedge(t1,t2,t3);
}
for(int i=; i<=n; i++)
{
addedge(st,i,inf);
}
dinic();
dfs1(st);
dfs2(ed);
// cout<<1<<endl;
int flag=;
for(int i=; i<l; i++)
{
// cout<<i<<endl;
if(edge[line[i]].flow==&&vis1[edge[line[i]].fr]&&vis2[edge[line[i]].to])
{
// cout<<i<<endl;
if(flag)
{
printf("%d",i+);
flag=;
}
else
{
printf(" %d",i+);
}
}
}
printf("\n");
}
return ;
}

B - Internship (网络流关键割边)的更多相关文章

  1. POJ3204 Ikki's Story - Road Reconstruction 网络流图的关键割边

    题目大意:一个有源有汇的城市,问最少增加城市中的多少道路可以增加源到汇上各个路径上可容纳的总车流量增加. 网络流关键割边集合指如果该边的容量增加,整个网络流图中的任意从原点到汇点的路径的流量便可增加. ...

  2. ZOJ 2532 Internship(最大流找关键割边)

    Description CIA headquarter collects data from across the country through its classified network. Th ...

  3. poj 3204(最小割--关键割边)

    Ikki's Story I - Road Reconstruction Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 7 ...

  4. Internship-ZOJ2532(网络流求割边)

    Internship Time Limit: 5 Seconds      Memory Limit: 32768 KB CIA headquarter collects data from acro ...

  5. POJ 3204 Ikki's Story I-Road Reconstruction (网络流关键边)

    [题意]给定一个N个节点M条边的网络流,求有多少条边,使得当增其中加任何一个边的容量后,整个网络的流将增加. 挺好的一道题,考察对网络流和增广路的理解. [思路] 首先关键边一定是满流边.那么对于一个 ...

  6. Soj题目分类

    -----------------------------最优化问题------------------------------------- ----------------------常规动态规划 ...

  7. OI网络流 简单学习笔记

    持续更新! 基本上只是整理了一下框架,具体的学习给出了个人认为比较好的博客的链接. ..怎么说呢,最基础的模板我就我不说了吧qwq,具体可以参考一下这位大佬写的博客:最大流,最小割,费用流 费用流 跑 ...

  8. POJ 1486 Sorting Slides (二分图关键匹配边)

    题意 给你n个幻灯片,每个幻灯片有个数字编号1~n,现在给每个幻灯片用A~Z进行编号,在该幻灯片范围内的数字都可能是该幻灯片的数字编号.问有多少个幻灯片的数字和字母确定的. 思路 确定幻灯片的数字就是 ...

  9. ZOJ 2587 Unique Attack (最小割唯一性)

    题意 判断一个无向图的割是否唯一 思路 错误思路:一开始想的是判断割边是否都是关键割边,那既然割边两端点能连通S.T点的边是关键边,那么只要遇到有某个边两端点不连通S or T则这条边就不是关键割边( ...

随机推荐

  1. Java_常用工具类收集

    一.日期工具类 package com.ebd.application.common.utils; import java.sql.Timestamp; import java.text.DateFo ...

  2. JavaScript限制前端页面用户表单输入

    onkeyup事件 onkeyup 事件会在键盘按键被松开时发生. 内容来源:自成e家 1.只能输入数字 <input onkeyup = "value=value.replace(/ ...

  3. day21 正则表达式

    正则表达式 简单的范围的字符组 0-9 匹配所有的数字 a-z 匹配所有的小写字母 A-Z 匹配所有的大写字母 A-Za-z 匹配所有的字母 字符 . 换行符以外的任意字符 \w word 匹配数字, ...

  4. Elasticsearch GC 时间过长的解决方法

    前言:GC 时间过长是个常见的问题,下文我将对应的现象和解决方案进行阐述.为什么这么解决,可以参考我的另外一个博客中的内存使用和GC指标这个章节 我们有时会发现elasticsearch集群挂掉,或者 ...

  5. JAVA8给我带了什么——流(入门)

    JAVA8有一个新功能——流.笔者简单的看一下流.然后默默的闭上眼睛.感叹一声:这不是.NET里面的Linq吗?如果你们当中有谁做过.NET程序员的话,对于流的学习其实帮助是很大的.但是要明白你现在是 ...

  6. 【CH1602】最大异或和 trie+贪心

    题目大意:给定 N 个数,求这 N 个数中任选两个数进行异或运算,求最大的异或和是多少. 一个 int 类型的整数,可以看作一个长度为32位的字符串,异或运算不像加法,最大值不一定是由两个较大值得到. ...

  7. (转)synchronized和lock的区别

    背景:最近在准备java基础知识,对于可重入锁一直没有个清晰的认识,有必要对这块知识进行总结. 1 . 什么是可重入锁 锁的概念就不用多解释了,当某个线程A已经持有了一个锁,当线程B尝试进入被这个锁保 ...

  8. my live bigdata

    s 上海移动 13585845289 张xx,安徽六安,下沙镇,沪南公路,X菇种植. 自然人严重失信黑名单查询 http://www.jscredit.gov.cn/credit/p/rb_list/ ...

  9. python---redis缓存页面前戏之剖析render源码

    1.初始代码: def get(self, *args, **kwargs): import time tm = time.time() self.render('home/index.html', ...

  10. redis分布式工具类 ----RedisShardedPoolUtil

    这个是redis分布式的工具类,看非分布式的看  这里 说一下redis的分布式,分布式,无疑,肯定不是一台redis服务器.假如说,我们有两台redis服务器,一个6379端口,一个6380端口.那 ...