Power Network(网络流最大流 & dinic算法 + 优化)
Time Limit: 2000MS | Memory Limit: 32768K | |
Total Submissions: 24019 | Accepted: 12540 |
Description

An example is in figure 1. The label x/y of power station u shows that p(u)=x and pmax(u)=y. The label x/y of consumer u shows that c(u)=x and cmax(u)=y. The label x/y of power transport line (u,v) shows that l(u,v)=x and lmax(u,v)=y. The power consumed is Con=6. Notice that there are other possible states of the network but the value of Con cannot exceed 6.
Input
Output
Sample Input
2 1 1 2 (0,1)20 (1,0)10 (0)15 (1)20
7 2 3 13 (0,0)1 (0,1)2 (0,2)5 (1,0)1 (1,2)8 (2,3)1 (2,4)7
(3,5)2 (3,6)5 (4,2)7 (4,3)5 (4,5)1 (6,0)5
(0)5 (1)2 (3)2 (4)1 (5)4
Sample Output
15
6
Hint
Source
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define MAXN 202
const int INT_MAX = 0x3f3f3f3f ;
int s, t;
int n, np, nc, m;
char str[];
int c[MAXN][MAXN];
int f[MAXN][MAXN];
int e[MAXN];
int h[MAXN];
void push(int u, int v)
{
int d = min(e[u], c[u][v] - f[u][v]);
f[u][v] += d;
f[v][u] = -f[u][v];
e[u] -= d;
e[v] += d;
}
bool relabel(int u)
{
int mh = INT_MAX;
for(int i=; i<n+; i++)
{
if(c[u][i] > f[u][i])
mh = min(mh, h[i]);
}
if(mh == INT_MAX)
return false; //残留网络中无从u出发的路
h[u] = mh + ;
for(int i=; i<n+; i++)
{
if(e[u] == ) //已无余流,不需再次push
break;
if(h[i] == mh && c[u][i] > f[u][i]) //push的条件
push(u, i);
}
return true;
}
void init_preflow()
{
memset(h, , sizeof(h));
memset(e, , sizeof(e));
h[s] = n+;
for(int i=; i<n+; i++)
{
if(c[s][i] == )
continue;
f[s][i] = c[s][i];
f[i][s] = -f[s][i];
e[i] = c[s][i];
e[s] -= c[s][i];
}
}
void push_relabel()
{
init_preflow();
bool flag = true; //表示是否还有relabel操作
while(flag)
{
flag = false;
for(int i=; i<n; i++)
if(e[i] > )
flag = flag || relabel(i);
}
}
int main()
{
while(scanf("%d%d%d%d", &n, &np, &nc, &m) != EOF)
{
s = n; t = n+;
memset(c, , sizeof(c));
memset(f, , sizeof(f));
while(m--)
{
scanf("%s", &str);
int u=, v=, z=;
sscanf(str, "(%d,%d)%d", &u, &v, &z);
c[u][v] = z;
}
for(int i=; i<np+nc; i++)
{
scanf("%s", &str);
int u=, z=;
sscanf(str, "(%d)%d", &u, &z);
if(i < np)
c[s][u] = z;
else if(i >= np && i < np + nc)
c[u][t] = z;
}
push_relabel();
printf("%d\n", e[t]);
}
}
dinic递归 110ms / 非递归 110 或 94 ms:http://hefeijack.iteye.com/blog/1885944
dinic 63ms/SAP 63 ms:http://www.cnblogs.com/kuangbin/archive/2012/09/11/2680908.html
dinic 63ms :http://blog.csdn.net/u011721440/article/details/38611197
初学者可以先去poj1273试试水=。=
这道题只要加一个 源点 和 汇点 , 就万事大吉了。
自己写了一遍,用dinic的递归形式,一开始tle,但就加了一句话,813msAC,
貌似是一种优化,但为啥不清楚。
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
const int M = , inf = 0x3f3f3f3f ;
int m , n ;
int map[M][M] ;
int dis[M]; bool bfs ()
{
queue <int> q ;
while (!q.empty ())
q.pop () ;
memset (dis , 0xff , sizeof(dis)) ;
dis[] = ;
q.push () ;
while (!q.empty () ) {
int u = q.front () ;
q.pop () ;
for (int v = ; v <= n ; v++) {
if (map[u][v] && dis[v] == -) {
dis[v] = dis[u] + ;
q.push (v) ;
}
}
}
if (dis[n] > )
return true ;
return false ;
} int find (int u , int low)
{
int a = ;
if (u == n)
return low ;
for (int v = ; v <= n ; v++) {
if (map[u][v] && dis[v] == dis[u] + && (a = find (v , min(map[u][v] , low)))) {
map[u][v] -= a ;
map[v][u] += a ;
return a ;
}
}
dis[u] = - ;//就这句
return ;
} int main ()
{
//freopen ("b.txt" , "r" , stdin) ;
int u , v , w ;
int ans ;
while (~ scanf ("%d%d" , &m , &n)) {
memset (map , , sizeof(map)) ;
while (m--) {
scanf ("%d%d%d" , &u , &v , &w) ;
map[u][v] += w ;
}
int maxn = ;
while (bfs()) {
if (ans = find( , inf))
maxn += ans ;
}
printf ("%d\n" , maxn) ;
}
return ;
}
用邻接表可以进一步优化(但上面那句话仍要加):因为用矩阵的话在find 和 bfs 时找点都要遍历一遍所有的点,但用邻接表的话可以很快找到。
110msAC:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
const int M = , inf = 0x3f3f3f3f ;
struct edge
{
int u , v , time_u ;
int w ;
}e[M * M * ];
int n , np , nc , m ;
int src , des ;
int cnt = ;
int dis[M] ;
char st[] ;
int head[M * M * ] ; void addedge (int u , int v , int w)
{
e[cnt].u = u ; e[cnt].v = v ; e[cnt].w = w ; e[cnt].time_u = head[u] ;
head[u] = cnt++ ;
e[cnt].v = u ; e[cnt].u = v ; e[cnt].w = ; e[cnt].time_u = head[v] ;
head[v] = cnt++ ;
}
bool bfs ()
{
queue <int> q ;
while (!q.empty ())
q.pop () ;
memset (dis , - , sizeof(dis)) ;
dis[src] = ;
q.push (src) ;
while (!q.empty ()) {
int u = q.front () ;
q.pop () ;
for (int i = head[u] ; i != - ; i = e[i].time_u) {
int v = e[i].v ;
if (dis[v] == - && e[i].w > ) {
dis[v] = dis[u] + ;
q.push (v) ;
}
}
}
if (dis[des] > )
return true ;
return false ;
} int find (int u , int low)
{
int a = ;
if (u == des)
return low ;
for (int i = head[u] ; i != - ; i = e[i].time_u) {
int v = e[i].v ;
if (e[i].w > && dis[v] == dis[u] + && (a = find(v , min (low , e[i].w)))) {
e[i].w -= a ;
e[i^].w += a ;
return a ;
}
}
dis[u] = - ;
return false ;
} int main ()
{
// freopen ("a.txt" , "r" , stdin) ;
int u , v , w ;
while (~ scanf ("%d%d%d%d" , &n , &np , &nc , &m)) {
src = n ;
des = n + ;
cnt = ;
memset (head , - , sizeof(head)) ;
while (m--) {
scanf ("%s" , st) ;
sscanf (st , "(%d,%d)%d" , &u , &v , &w) ;
addedge(u , v , w) ;
}
while (np--) {
scanf ("%s" , st) ;
sscanf (st , "(%d)%d" , &v , &w) ;
addedge (src , v , w) ;
}
while (nc--) {
scanf ("%s" , st) ;
sscanf (st , "(%d)%d" , &u , &w) ;
addedge (u , des , w) ;
} int ans = , res = ;
while (bfs()) {
while () {
if (ans = find(src , inf))
res += ans ;
else
break ;
}
}
printf ("%d\n" , res) ;
}
return ;
}
head[u]用来存放点u最新出现的时间 ,感觉和tarjan算法中的dfn[u]差不多;
time_u则保存上一次点u出现的时间 。
Power Network(网络流最大流 & dinic算法 + 优化)的更多相关文章
- POJ训练计划1459_Power Network(网络流最大流/Dinic)
解题报告 这题建模实在是好建.,,好贱.., 给前向星给跪了,纯dinic的前向星居然TLE,sad.,,回头看看优化,.. 矩阵跑过了.2A,sad,,, /******************** ...
- 网络流最大流——dinic算法
前言 网络流问题是一个很深奥的问题,对应也有许多很优秀的算法.但是本文只会讲述dinic算法 最近写了好多网络流的题目,想想看还是写一篇来总结一下网络流和dinic算法以免以后自己忘了... 网络流问 ...
- [讲解]网络流最大流dinic算法
网络流最大流算法dinic ps:本文章不适合萌新,我写这个主要是为了复习一些细节,概念介绍比较模糊,建议多刷题去理解 例题:codevs草地排水,方格取数 [抒情一下] 虽然老师说这个多半不考,但是 ...
- POJ 1459 Power Network(网络流 最大流 多起点,多汇点)
Power Network Time Limit: 2000MS Memory Limit: 32768K Total Submissions: 22987 Accepted: 12039 D ...
- POJ1459 Power Network 网络流 最大流
原文链接http://www.cnblogs.com/zhouzhendong/p/8326021.html 题目传送门 - POJ1459 题意概括 多组数据. 对于每一组数据,首先一个数n,表示有 ...
- 网络流——最大流Dinic算法
前言 突然发现到了新的一年什么东西好像就都不会了凉凉 算法步骤 建残量网络图 在残量网络图上跑增广路 重复1直到没有增广路(注意一个残量网络图要尽量把价值都用完,不然会浪费建图的时间) 代码实现 #i ...
- 网络流之最大流Dinic算法模版
/* 网络流之最大流Dinic算法模版 */ #include <cstring> #include <cstdio> #include <queue> using ...
- hdu-3572 Task Schedule---最大流判断满流+dinic算法
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3572 题目大意: 给N个任务,M台机器.每个任务有最早才能开始做的时间S,deadline E,和持 ...
- 网络流(最大流-Dinic算法)
摘自https://www.cnblogs.com/SYCstudio/p/7260613.html 网络流定义 在图论中,网络流(Network flow)是指在一个每条边都有容量(Capacity ...
随机推荐
- EventBus框架在Android多Pane(Fragment)中的应用
通常多pane的设计中,比如Fragment A是个Headline,Fragement B是detail,那么B通常需要实现A的点击事件的接口,这样子的话,两个fragment就高耦合了,而且需要在 ...
- 分享两个你可能不知道的Java小秘密
引言 最近LZ的工作发生了重大变化,以后博文的更新速度可能会再度回温,希望猿友们可以继续关注. 近期LZ辞掉了项目经理的工作,不过并未离开公司,是转到了基础研发部做更基础的研发,为广大技术人员服务.这 ...
- Dictionary使用
/// <summary> /// 除去数组中的空值和签名参数并以字母a到z的顺序排序 /// </summary> /// <param name="dicA ...
- 第二十三课:jQuery.event.add的原理以及源码解读
本课主要来讲解一下jQuery是如何实现它的事件系统的. 我们先来看一个问题: 如果有一个表格有100个tr元素,每个都要绑定mouseover/mouseout事件,改成事件代理的方式,可以节省99 ...
- 第十四课:js操作节点的插入,复制,移除
节点插入 appendChild方法,insertBefore方法是常用的两个节点插入方法,具体实现,请看js高级程序设计,或者自行百度. 这里提一下面试时经常会问到的问题,插入多个节点时,你是怎么插 ...
- “耐撕”团队 2016.3.25 站立会议
成员: Z 郑蕊 * 组长 (博客:http://www.cnblogs.com/zhengrui0452/), P 濮成林(博客:http://www.cnblogs.com/charliePU/) ...
- 另一套Oracle SQL练习题,更新参考答案
题干: create table student( sno ) primary key, sname ), sage ), ssex ) ); create table teacher( tno ) ...
- iOS边练边学--父子控件之作为导航控制器的子类产生的问题以及网易新闻练习
一.导航控制器的子类 作为导航控制器的子类,并且是导航控制器子类中的第一个,系统会默认给子控件添加EdgeInsert属性,把导航栏的宽度挤出来.但是系统只会默认修改第一个. 解决办法1:系统帮忙给第 ...
- py替换掉换行符
for line in file.readlines(): line=line.strip('\n')
- Ubuntu 12.10安装OpenGL
http://wiki.ubuntu-tw.org/index.php?title=Howto_Install_OpenGL_Development_Environment 前言 OpenGL 是一套 ...