POJ3204 Ikki's Story - Road Reconstruction 网络流图的关键割边
题目大意:一个有源有汇的城市,问最少增加城市中的多少道路可以增加源到汇上各个路径上可容纳的总车流量增加。
网络流关键割边集合指如果该边的容量增加,整个网络流图中的任意从原点到汇点的路径的流量便可增加。
从源点开始遍历未满流的边,这些边两端节点的集合称为S;同理再从汇点开始遍历,集合称为T;其余的点组成另一个集合。如果一个边是最小割,则其两端属于不同的集合。如果一个边是关键割边,则该边两端节点一个属于S,一个属于T。遍历每一个图中的边,看它是否满足该条件即可。
#include <cstdio>
#include <cstring>
#include <cassert>
#include <cmath>
#include <algorithm>
using namespace std; const int NODE_MAX = 1100, EDGE_MAX = 10100, INF = 0x3f3f3f3f; //below:for dinic-----------------------------------------------------
struct Node;
struct Edge; struct Node
{
int Id, Vis;
int Level;
Edge *Head;
}; struct Edge
{
int Cap, Id;
Edge* Rev, *Next;
Node *From, *To;
}; Node _nodes[NODE_MAX];
Edge _edges[EDGE_MAX];
int _lastVId, _eCount = 0;
Node *StartNode, *TargetNode; void Init()
{
memset(_nodes, 0, sizeof(_nodes));
memset(_edges, 0, sizeof(_edges));
_eCount = 0;
} Edge *NewEdge()
{
return ++_eCount + _edges;
} void SetST(int sId, int tId)
{
StartNode = _nodes + sId;
TargetNode = _nodes + tId;
} void SetLastVId(int vId)
{
_lastVId = vId;
} Edge *AddEdge(Node *from, Node *to, int id, int cap)
{
Edge *e = NewEdge();
e->Id = id;
e->From = from;
e->To = to;
e->Cap = cap;
e->Next = e->From->Head;
e->From->Head = e;
return e;
} void Build(int uId, int vId, int id, int cap)
{
Node *u = uId + _nodes, *v = vId + _nodes;
u->Id = uId;
v->Id = vId;
Edge *e1 = AddEdge(u, v, id, cap);
Edge *e2 = AddEdge(v, u, -id, 0);
e1->Rev = e2;
e2->Rev = e1;
} struct NodeQueue
{
Node *q[NODE_MAX];
int head, tail;
void clear() { head = tail = 0; }
void push(Node *v) { q[tail++] = v; }
Node* front() { return q[head]; }
void pop() { head++; }
bool empty() { return head == tail; }
}; bool Bfs()
{
for (int i = 0; i <= _lastVId; i++)
_nodes[i].Level = 0;
NodeQueue q;
q.clear();
StartNode->Level = 1;
q.push(StartNode);
while (!q.empty())
{
Node *cur = q.front();
q.pop();
for (Edge *e = cur->Head; e; e = e->Next)
{
if (!e->To->Level && e->Cap)
{
e->To->Level = cur->Level + 1;
q.push(e->To);
}
}
}
return TargetNode->Level;
} int Dfs(Node *cur, int limit)
{
if (cur == TargetNode)
return limit;
if (limit == 0)
return 0;
int curTake = 0;
for (Edge *e = cur->Head; e; e = e->Next)
{
if (e->To->Level == cur->Level + 1 && e->Cap)
{
int nextTake = Dfs(e->To, min(limit - curTake, e->Cap));
e->Cap -= nextTake;
e->Rev->Cap += nextTake;
curTake += nextTake;
}
}
return curTake;
} int Dinic()
{
int ans = 0;
while (Bfs())
ans += Dfs(StartNode, INF);
return ans;
}
//above:for dinic----------------------------------------------------- void Dfs1(Node *cur)
{
assert(!cur->Vis);
cur->Vis = 1;
for (Edge *e = cur->Head; e; e = e->Next)
if (e->Cap && !e->To->Vis && e->Id > 0)
Dfs1(e->To);
} void Dfs2(Node *cur)
{
assert(cur->Vis != 1);
cur->Vis = 2;
for (Edge *e = cur->Head; e; e = e->Next)
if (e->Rev->Cap && !e->To->Vis &&e->Rev->Id > 0)
Dfs2(e->To);
} int main()
{
freopen("c:\\noi\\source\\input.txt", "r", stdin);
int totCity, totEdge;
scanf("%d%d", &totCity,&totEdge);
Init();
SetLastVId(totCity - 1);
SetST(0, totCity - 1);
int uId, vId, cap;
for (int i = 1; i <= totEdge; i++)
{
scanf("%d%d%d", &uId, &vId, &cap);
Build(uId, vId, i, cap);
}
Dinic();
Dfs1(StartNode);
Dfs2(TargetNode);
int eId[EDGE_MAX], pe = 0;
memset(eId, 0, sizeof(eId));
for (int i = 1; i <= _eCount; i++)
if (_edges[i].From->Vis == 1 && _edges[i].To->Vis == 2 && _edges[i].Id > 0)
eId[pe++] = _edges[i].Id;
sort(eId, eId + pe);
printf("%d\n", pe);
return 0;
}
POJ3204 Ikki's Story - Road Reconstruction 网络流图的关键割边的更多相关文章
- poj3204Ikki's Story I - Road Reconstruction(最大流求割边)
链接 最大流=最小割 这题是求割边集 dinic求出残余网络 两边dfs分别以源点d找到可达点 再以汇点进行d找到可达汇点的点 如果u,v为割边 那么s->u可达 v->t可达 并且为饱 ...
- POJ3204 Ikki's Story I - Road Reconstruction
Ikki's Story I - Road Reconstruction Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 7 ...
- POJ 3204 Ikki's Story I - Road Reconstruction
Ikki's Story I - Road Reconstruction Time Limit: 2000MS Memory Limit: 131072K Total Submissions: 7 ...
- POJ3184 Ikki's Story I - Road Reconstruction(最大流)
求一次最大流后,分别对所有满流的边的容量+1,然后看是否存在增广路. #include<cstdio> #include<cstring> #include<queue& ...
- POJ 3204 Ikki's Story I-Road Reconstruction (网络流关键边)
[题意]给定一个N个节点M条边的网络流,求有多少条边,使得当增其中加任何一个边的容量后,整个网络的流将增加. 挺好的一道题,考察对网络流和增广路的理解. [思路] 首先关键边一定是满流边.那么对于一个 ...
- POJ-3204-Ikki's Story I - Road Reconstruction(最大流)
题意: 给一个有向图 求给那些边增加容量能增加总的流量,求边的条数 分析: 一开始求的是割边,结果wa了,那是因为有些割边增加了容量,但总的容量也不会增加 只有满流的边并且从源点汇点都有一条可扩展的路 ...
- 一起来全面解析5G网络领域最关键的十大技术
提到5G,很多人的第一印象就是它的网络速度快.延时性低.带宽大,没错,这就是5G时代的特点!5G作为第五代移动通信网络,其峰值理论传输速度可达每秒数十Gb,这比4G网络的传输速度快数百倍,整部超高画质 ...
- UVA11248 网络扩容(枚举割边扩充)
题意: 给你一个有向图,问你从1到n的最大流是多少?如果流量大于等于C那么直接输出一个串,否则输出只扩充一条边的流量就可以达到1->n大于等于C的所有边,如果扩充不了就输出另一个串.S ...
- [POJ3352]Road Construction(缩点,割边,桥,环)
题目链接:http://poj.org/problem?id=3352 给一个图,问加多少条边可以干掉所有的桥. 先找环,然后缩点.标记对应环的度,接着找桥.写几个例子就能知道要添加的边数是桥的个数/ ...
随机推荐
- 高通处理器手机 解锁Bootloader 教程
目前很多手机都需要解锁Bootloader之后才能进行刷机操作 本篇教程教你如何傻瓜式解锁Bootloader 首先需要在设置-关于手机 找到版本号(个别手机可能是内核版本号,甚至其他) 然后 快 ...
- C# 连接 access2010数据库
//定义一个新的OleDb连接 System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection(); // ...
- Deutsch lernen (09)
1. die Rückmeldung, -en 反馈,回馈:(销假)报到 die Rückmeldung zur Arbeit 2. dringend a. 紧急的,急切的 Ich brauche d ...
- VHDL之FSM
1 Intro The figure shows the block diagram of a single-phase state machine. The lower section contai ...
- 读书笔记「Python编程:从入门到实践」_9.类
9.1 创建和使用类 面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想. OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 把 ...
- ApplicationLoader登录失败
报错:Please sign in with an app-specific password. You can create one at appleid.apple.com 是因为帐号开启了双重认 ...
- 两个控件同一行显示bootstrap
<div class="form-group"> <label for="Name" class="form-inline" ...
- 基于MATLAB的语音信号处理
一.图形界面设计 1.新建GUI界面 2.新建空白页 3.命名为"yydsp",打开界面 4.拖放控件 5.按预定功能修改界面 6.填写Callback函数 未填写前的代码: fu ...
- 分别用for循环,while do-while以及递归方法实现n的阶乘!
分别用for循环,while do-while以及递归方法实现n的阶乘! 源码: package book;import java.util.Scanner;public class Access { ...
- nyoj24-素数 距离问题
素数距离问题 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 现在给出你一些数,要求你写出一个程序,输出这些整数相邻最近的素数,并输出其相距长度.如果左右有等距离长度素数 ...