题目链接: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. BZOJ1500[NOI2005]维修数列——非旋转treap

    题目描述 请写一个程序,要求维护一个数列,支持以下 6 种操作: 请注意,格式栏 中的下划线‘ _ ’表示实际输入文件中的空格 输入 输入的第1 行包含两个数N 和M(M ≤20 000),N 表示初 ...

  2. Codeforces 741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(dsu on tree)

    感觉dsu on tree一定程度上还是与点分类似的.考虑求出跨过每个点的最长满足要求的路径,再对子树内取max即可. 重排后可以变成回文串相当于出现奇数次的字母不超过1个.考虑dsu on tree ...

  3. SpringBoot基础入门

    1.SpringBoot核心相关内容 1.1入口类 SpringBoot通常有一个入口类*Application,内部有一个main方法,是启动SpringBoot的入口.使用@SpringBootA ...

  4. 自学Linux Shell5.1-shell父子关系

    点击返回 自学Linux命令行与Shell脚本之路 5.1-shell父子关系 1 shell常见的种类  bash是Linux标准默认的Shell,是BunrneAgain Shell的缩写,内部命 ...

  5. SwitchButton 开关按钮 的多种实现方式 (附源码DEMO)

    http://blog.csdn.net/vipzjyno1/article/details/23707149 Switch开关android源码SwitchButton 刚开始接触开关样式的按钮是在 ...

  6. Segment 李超线段树

    题目大意: 要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第 i 条被插入的线段的标号为 i 2.给定一个数 k,询问与直线 x = k 相交的线段中,交点最靠上的线段的编号. 若 ...

  7. 洛谷P3953 逛公园

    DP+图论大毒瘤. 推荐这个博客. 先跑两遍最短路,搞掉一些无用点. 然后选出最短路上的边,做拓扑排序. 然后每层DP. 具体看代码. 用到的数组较多,记得清空. #include <cstdi ...

  8. poj 3678(SCC+2-SAT)

    传送门:Problem 3678 https://www.cnblogs.com/violet-acmer/p/9769406.html 难点: 题意理解+构图 题意: 有n个点 v[0,2..... ...

  9. CalISBN.java

    /****************************************************************************** * Compilation: javac ...

  10. css 实现背景图片不跟着滚动条滚动而滚动

    效果: 只需要在需要背景不跟着动的div里: div{ background:url(); background-attachment:fixed; } 加上background-attachment ...