poj 3204(最小割--关键割边)
| Time Limit: 2000MS | Memory Limit: 131072K | |
| Total Submissions: 7491 | Accepted: 2172 |
Description
Ikki is the king of a small country – Phoenix, Phoenix is so small that there is only one city that is responsible for the production of daily goods, and uses the road network to transport the goods to the capital. Ikki finds that the biggest problem in the country is that transportation speed is too slow.
Since Ikki was an ACM/ICPC contestant before, he realized that this, indeed, is a maximum flow problem. He coded a maximum flow program and found the answer. Not satisfied with the current status of the transportation speed, he wants to increase the transportation ability of the nation. The method is relatively simple, Ikki will reconstruct some roads in this transportation network, to make those roads afford higher capacity in transportation. But unfortunately, the country of Phoenix is not so rich in GDP that there is only enough money to rebuild one road. Ikki wants to find such roads that if reconstructed, the total capacity of transportation will increase.
He thought this problem for a loooong time but cannot get it. So he gave this problem to frkstyc, who put it in this POJ Monthly contest for you to solve. Can you solve it for Ikki?
Input
The input contains exactly one test case.
The first line of the test case contains two integers N, M (N ≤ 500, M ≤ 5,000) which represents the number of cities and roads in the country, Phoenix, respectively.
M lines follow, each line contains three integers a, b, c, which means that there is a road from city a to city b with a transportation capacity of c (0 ≤ a, b < n, c ≤ 100). All the roads are directed.
Cities are numbered from 0 to n − 1, the city which can product goods is numbered 0, and the capital is numbered n − 1.
Output
Sample Input
2 1
0 1 1
Sample Output
1 题意:从源点0到汇点n-1,问给那些边增加容量会增大整个网络的容量??输出边的数量。
这里有个重要的概念:关键边,关键边定义为 :通过增加某个边的容量使得网络的最大流增加
个人的理解为最小割里面的边一定是关键割边,但关键割边不一定是最小割。
这题的做法是先求一次最大流,然后对残余网络进行两次DFS,从源点的DFS很简单,从正向边搜到边的容量为0即可,得到点集A,标记;主要是从汇点进行第二次DFS,这里就要用到技巧了,网络流有个神奇的反向边,我们从反向边进行DFS(也要判断一下正向边是否为0)得到点集B,标记;然后遍历所有的边,如果某条边的两个端点分别属于点集 A,B,那么这条边肯定就是关键割边,记录之。
#include <stdio.h>
#include <algorithm>
#include <queue>
#include <string.h>
#include <math.h>
#include <iostream>
#include <math.h>
using namespace std;
const int N = ;
const int INF = ;
struct Edge
{
int v,next;
int w;
} edge[N*N];
int head[N];
int level[N];
int tot;
void init()
{
memset(head,-,sizeof(head));
tot=;
}
void addEdge(int u,int v,int w,int &k)
{
edge[k].v = v,edge[k].w=w,edge[k].next=head[u],head[u]=k++;
edge[k].v = u,edge[k].w=,edge[k].next=head[v],head[v]=k++;
}
int BFS(int src,int des)
{
queue<int >q;
memset(level,,sizeof(level));
level[src]=;
q.push(src);
while(!q.empty())
{
int u = q.front();
q.pop();
if(u==des) return ;
for(int k = head[u]; k!=-; k=edge[k].next)
{
int v = edge[k].v;
int w = edge[k].w;
if(level[v]==&&w!=)
{
level[v]=level[u]+;
q.push(v);
}
}
}
return -;
}
int dfs(int u,int des,int increaseRoad)
{
if(u==des) return increaseRoad;
int ret=;
for(int k=head[u]; k!=-; k=edge[k].next)
{
int v = edge[k].v;
int w = edge[k].w;
if(level[v]==level[u]+&&w!=)
{
int MIN = min(increaseRoad-ret,w);
w = dfs(v,des,MIN);
if(w>)
{
edge[k].w -=w;
edge[k^].w+=w;
ret+=w;
if(ret==increaseRoad) return ret;
}
else level[v] = -;
}
}
return ret;
}
int Dinic(int src,int des)
{
int ans = ;
while(BFS(src,des)!=-) ans+=dfs(src,des,INF);
return ans;
}
int vis[N];
void dfs0(int u)
{
vis[u] = ;
for(int k=head[u]; k!=-; k=edge[k].next)
{
int v = edge[k].v,w = edge[k].w; if(!vis[v]&&w>)
{
dfs0(v);
}
}
}
void dfs1(int u)
{
vis[u] = ;
for(int k=head[u]; k!=-; k=edge[k].next)
{
int v = edge[k].v;
if(!vis[v]&&edge[k^].w>&&edge[k].w>) ///汇点利用反向边进行搜索,这里还要判断一下正向边是否大于0
{
dfs1(v);
}
}
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
init();
for(int i=; i<m; i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(u==v) continue;
addEdge(u,v,w,tot);
}
memset(vis,,sizeof(vis));
Dinic(,n-);
dfs0();
dfs1(n-);
int ans = ;
for(int u=; u<n; u++)
{
for(int k=head[u]; k!=-; k=edge[k].next)
{
if(k%==) continue; ///只考虑正向边
if(vis[u]==&&vis[edge[k].v]==) ans++;
}
}
printf("%d\n",ans);
}
poj 3204(最小割--关键割边)的更多相关文章
- HDU 3251 Being a Hero(最小割+输出割边)
Problem DescriptionYou are the hero who saved your country. As promised, the king will give you some ...
- poj 2125(最小割)
题目链接:http://poj.org/problem?id=2125 思路:将最小点权覆盖转化为最小割模型,于是拆点建图,将点i拆成i,i+n,其中vs与i相连,边容量为w[i]-,i+n与vt相连 ...
- POJ 3469 最小割 Dual Core CPU
题意: 一个双核CPU上运行N个模块,每个模块在两个核上运行的费用分别为Ai和Bi. 同时,有M对模块需要进行数据交换,如果这两个模块不在同一个核上运行需要额外花费. 求运行N个模块的最小费用. 分析 ...
- poj1815Friendship(最小割求割边)
链接 题意为去掉多少个顶点使图不连通,求顶点连通度问题.拆点,构造图,对于<u,v>可以变成<u2,v1> <v2,u1>容量为无穷,<u1,u2>容量 ...
- 网络流 poj 3308 最小割
t个样例 n*m的矩阵 L个伞兵 给出每行每列装激光的花费 伞兵的位置 要求杀死所有伞兵 总费用为这些费用的乘积 求花费最小 建图 源点 -> 行 -> 列 -> 汇点 ...
- [BZOJ 1797][AHOI2009]最小割(最小割关键边的判断)
题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1797 分析: 在残余网络中看: 对于第1问: 1.首先这个边必须是满流 2.其次这个边 ...
- poj 3084 最小割
题目链接:http://poj.org/problem?id=3084 本题主要在构图上,我采用的是把要保护的房间与源点相连,有intruder的与汇点相连,相对麻烦. #include <cs ...
- HDU3987(最小割最少割边)
Harry Potter and the Forbidden Forest Time Limit: 5000/3000 MS (Java/Others) Memory Limit: 65536/ ...
- poj 3469 最小割模板sap+gap+弧优化
/*以核心1为源点,以核心2为汇点建图,跑一遍最大流*/ #include<stdio.h> #include<string.h> #include<queue> ...
随机推荐
- python 面对对象基础
目录 面向对象基础 面向对象编程(抽象) 类与对象 给对象定制独有的特征 对象的属性查找顺序 类与对象的绑定方法 类与数据类型 对象的高度整合 面向对象基础 面向对象编程(抽象) 回顾一下 面向过程编 ...
- Java求字符串中出现次数最多的字符
Java求字符串中出现次数最多的字符 [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article/details/51933611 Java ...
- JAVA基础篇—异常
五种常见异常 1.NullPointerException 空指针 2.ClassNotFoundException 指定类不存在 3.ArithmeticException运算异常 4.ArrayI ...
- Aizu - 1378 Secret of Chocolate Poles (DP)
你有三种盘子,黑薄,白薄,黑厚. 薄的盘子占1,厚的盘子占k. 有一个高度为L的桶,盘子总高度不能超出桶的总高度(可以小于等于).相同颜色的盘子不能挨着放. 问桶内装盘子的方案数. 如 L = 5,k ...
- poj 3107 Godfather(树的重心)
Godfather Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 7885 Accepted: 2786 Descrip ...
- Oracle 了解 DDL 操作与 REDO 的关系
目录 了解 DDL 操作与 REDO 的关系 DDL是否会产生REDO 通过 10046 trace 来分析create 和drop 如果drop失败,redo的变化 了解 DDL 操作与 REDO ...
- EF知识和经验
AsNoTracking提高查询性能 AsNoTracking的作用就是在查询的时候不做追踪,这样会查询的更快,但是这样做会有一个缺陷(不能对查询的数据做修改操作). var student2 = d ...
- 进程,线程,以及Python的多进程实例
什么是进程,什么是线程? 进程与线程是包含关系,进程包含了线程. 进程是系统资源分配的最小单元,线程是系统任务执行的最小单元. 打个比方,打开word,word这个程序是一个进程,里面的拼写检查,字数 ...
- Xcode中断点的使用
注:本文由破船译自:albertopasca.本文由HoNooD在iosfeed站点上做了推荐. 这里先推荐两篇Xcode相关的文章: Xcode Code Snippets iOS调试 — 基本技巧 ...
- 《Spark Python API 官方文档中文版》 之 pyspark.sql (四)
摘要:在Spark开发中,由于需要用Python实现,发现API与Scala的略有不同,而Python API的中文资料相对很少.每次去查英文版API的说明相对比较慢,还是中文版比较容易get到所需, ...