UVA11248 网络扩容(枚举割边扩充)
题意:
给你一个有向图,问你从1到n的最大流是多少?如果流量大于等于C那么直接输出一个串,否则输出只扩充一条边的流量就可以达到1->n大于等于C的所有边,如果扩充不了就
输出另一个串。
Sample Input
4 4 5
1 2 5
1 3 5
2 4 5
3 4 5
4 4 5
1 2 1
1 3 5
2 4 5
3 4 1
4 4 5
1 2 1
1 3 1
2 4 1
3 4 1
0 0 0
Output for Sample Input
Case 1: possible
Case 2: possible option:(1,2),(3,4)
Case 3: not possible
思路:
很容易想到的一点就是扩展后有作用的点肯定是割边,那么我们可以先跑一遍最大流把割边找出来,然后枚举割边,扩充割边流量,看最大流是否大于等于C,但是这样会TLE,有两个比较有用的优化,就是每次都在残余网络上改流量,然后加上残余网络之前跑出来的流量,还有一个优化就是跑最大流的时候,如果当前流量大于等于C了就已经满足了,没必要再跑了。
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N_node 100 + 5
#define N_edge 20000 + 10
#define INF 2005000000
using namespace std;
typedef struct
{
int from ,to ,next;
long long cost;
}STAR;
typedef struct
{
int x ,t;
}DEP;
typedef struct
{
int a ,b;
}EDGE;
STAR E[N_edge] ,mkE[N_edge];
EDGE edge[N_edge] ,Ans_Edge[N_edge];
DEP xin ,tou;
int list[N_node] ,list2[N_node] ,mklist[N_node] ,tot;
int deep[N_node];
void add(int a ,int b ,long long c)
{
E[++tot].from = a;
E[tot].to = b;
E[tot].cost = c;
E[tot].next = list[a];
list[a] = tot;
E[++tot].from = b;
E[tot].to = a;
E[tot].cost = 0;
E[tot].next = list[b];
list[b] = tot;
}
bool camp(EDGE a ,EDGE b)
{
return a.a < b.a || a.a == b.a && a.b < b.b;
}
long long minn(long long a ,long long b)
{
return a < b ? a : b;
}
bool BFS_Deep(int s ,int t ,int n)
{
memset(deep ,255 ,sizeof(deep));
xin.x = s ,xin.t = 0;
deep[s] = 0;
queue<DEP>q;
q.push(xin);
while(!q.empty())
{
tou = q.front();
q.pop();
for(int k = list[tou.x] ;k ;k = E[k].next)
{
xin.x = E[k].to;
xin.t = tou.t + 1;
if(deep[xin.x] != -1 || !E[k].cost)
continue;
deep[xin.x] = xin.t;
q.push(xin);
}
}
for(int i = 0 ;i <= n ;i ++)
list2[i] = list[i];
return deep[t] != -1;
}
long long DFS_Flow(int s ,int t ,long long flow ,long long C)
{
if(s == t) return flow;
long long nowflow = 0;
for(int k = list2[s] ;k ;k = E[k].next)
{
list2[s] = k;
int to = E[k].to;
long long c = E[k].cost;
if(deep[to] != deep[s] + 1 || !c) continue;
long long tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow) ,C);
nowflow += tmp;
E[k].cost -= tmp;
E[k^1].cost += tmp;
if(nowflow == flow) break;
}
if(!nowflow) deep[s] = 0;
return nowflow;
}
long long DINIC(int s ,int t ,int n ,long long C)
{
long long Ans = 0;
while(BFS_Deep(s ,t ,n) && Ans < C)
{
Ans += DFS_Flow(s ,t ,INF ,C);
}
return Ans;
}
int main ()
{
int n ,m ,C ,cas = 1;
int a ,b ,c ,i ,j;
while(~scanf("%d %d %d" ,&n ,&m ,&C) && n + m + C)
{
memset(list ,0 ,sizeof(list)) ,tot = 1;
for(i = 1 ;i <= m ;i ++)
{
scanf("%d %d %d" ,&a ,&b ,&c);
add(a ,b ,(long long)c);
}
long long Ans = DINIC(1 ,n ,n ,C);
printf("Case %d: " ,cas ++);
if(Ans >= C)
{
printf("possible\n");
continue;
}
int nowid = 0;
for(i = 2 ;i <= tot ;i += 2)
{
mkE[i] = E[i] ,mkE[i+1] = E[i+1];
if(!E[i].cost)
{
edge[++nowid].a = E[i].from;
edge[nowid].b = E[i].to;
}
}
for(i = 1 ;i <= n ;i ++)
mklist[i] = list[i];
int Ans_Id = 0;
int mktot = tot;
for(i = 1 ;i <= nowid ;i ++)
{
add(edge[i].a ,edge[i].b ,C);
long long tmp = DINIC(1 ,n ,n ,C);
if(tmp + Ans >= C) Ans_Edge[++Ans_Id] = edge[i];
tot = mktot;
for(j = 2 ;j <= tot ;j ++) E[j] = mkE[j];
for(j = 1 ;j <= n ;j ++) list[j] = mklist[j];
}
if(!Ans_Id)
{
puts("not possible");
continue;
}
sort(Ans_Edge + 1 ,Ans_Edge + Ans_Id + 1 ,camp);
printf("possible option:");
for(i = 1 ;i <= Ans_Id ;i ++)
if(i != 1) printf(",(%d,%d)" ,Ans_Edge[i].a ,Ans_Edge[i].b);
else printf("(%d,%d)" ,Ans_Edge[i].a ,Ans_Edge[i].b);
puts("");
}
return 0;
}
UVA11248 网络扩容(枚举割边扩充)的更多相关文章
- C++之路进阶——codevs1362(网络扩容)
1362 网络扩容 省队选拔赛 时间限制: 2 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给定一张有向图,每条边都有一个容量 ...
- BZOJ-1834 网络扩容 最小费用最大流+最大流+乱搞
1834: [ZJOI2010]network 网络扩容 Time Limit: 3 Sec Memory Limit: 64 MB Submit: 2269 Solved: 1136 [Submit ...
- 【BZOJ】【1834】【ZJOI2010】Network 网络扩容
网络流/费用流 这题……我一开始sb了. 第一问简单的最大流…… 第二问是要建费用流的图的……但是是在第一问的最大流跑完以后的残量网络上建,而不是重建…… 我们令残量网络上原有的弧的费用全部为0(因为 ...
- bzoj1834: [ZJOI2010]network 网络扩容
努力看了很久样例一直过不了...然后各种输出中间过程啊巴拉巴拉弄了1h,没办法了...然后突然想到啊原来的边可以用啊为什么不用...于是A了...感人肺腑 #include<cstdio> ...
- BZOJ 1834: [ZJOI2010]network 网络扩容(最大流+最小费用最大流)
第一问直接跑最大流.然后将所有边再加一次,费用为扩容费用,容量为k,再从一个超级源点连一条容量为k,费用为0的边到原源点,从原汇点连一条同样的边到超级汇点,然 后跑最小费用最大流就OK了. ---- ...
- 【BZOJ1834】网络扩容(最大流,费用流)
[BZOJ1834]网络扩容(最大流,费用流) 题面 Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下 ...
- BZOJ_1834_[ZJOI2010]network 网络扩容_费用流
BZOJ_1834_[ZJOI2010]network 网络扩容_费用流 题意: 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求: 1.在不扩容的 ...
- 【题解】Luogu P2604 [ZJOI2010]网络扩容
原题传送门:P2604 [ZJOI2010]网络扩容 这题可以说是板题 给你一个图,先让你求最大流 再告诉你,每条边可以花费一些代价,使得流量加一 问至少花费多少代价才能使最大流达到k 解法十分简单 ...
- 【BZOJ1834】[ZJOI2010]network 网络扩容 最大流+最小费用流
[BZOJ1834][ZJOI2010]network 网络扩容 Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不 ...
随机推荐
- 订单和产品的多对多表关系在crudapi系统零代码实现
表关系管理 在上一篇序列号管理中,产品和销售订单都是孤立的单表,本文通过crudapi中表关系(relation)管理将多个表连接起来,形成一个整体. 概要 关系类型 表与表之间的关系(relatio ...
- there is nothing(i春秋CTF题解)
(1)打开页面,显示为:there is nothing (2)抓包发现提示 (3)hint:ip,Large internal network 意为最大的内网网段IP,hint: ip,Larg ...
- JAVA-标识符、变量、数据类型
标识符和关键字 所有的标识符否应该以字母a ~ z和 A ~Z ,美元符($).下划线(_)开始. 首字符之后可以是字母a ~ z和 A ~Z ,美元符($).下划线(_)的任意字符组合. 注 ...
- tomcat启动错误Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/ofuns]];
起初遇到这个问题的时候是在实训(开发环境选择的是IDEA)的时候,检查了半天未果,上网搜索之后,说的也是各式各样,最后发现问题出在web.xml上面 在配置 filter 的 url-pattern ...
- 键盘--扫描码--ASCII码--显示器上的字符
在上一篇,我讲了键盘操作会产生扫描码以及如何解析Pause键和Print Screen键的扫描码. 在这一篇,我会说清楚"键盘上的输入为什么会出现在显示器上". 极简版 我们敲击键 ...
- Nodejs学习笔记(2) 阻塞/非阻塞实例 与 Nodejs事件
1. Node.js异步编程的特点 2. 阻塞与非阻塞的实例 2.1 阻塞代码实例 2.2 非阻塞代码实例 3. Node.js的事件驱动 4. 事件循环实例 1. Node.js异步编程的特点 参考 ...
- 2.pandas常用读取
一.文本读写 名称 接收 代表(含义) 默认 filepath string 文件路径 无 sep string 分割符 ',' header Int/sequence 某行做列名 infer自动寻找 ...
- 根据数据渲染DOM树形菜单——中途感想
根据数据渲染DOM树形菜单,这个需求做了几天了.一开始觉得用while也可以实现一层一层查找数据,但后来发现while还是做不到,因为我查找这个动作必须有进入有出来然后进入下一个条目,但while只能 ...
- PTA 带头结点的链式表操作集
6-2 带头结点的链式表操作集 (20 分) 本题要求实现带头结点的链式表操作集. 函数接口定义: List MakeEmpty(); Position Find( List L, Element ...
- C++中的间接宏函数
宏函数对于每个C++程序员都决不陌生,就算是初出茅庐的C++程序员也知道如何定义.使用宏函数. 但是当初学者看到类似于以下这种宏函数嵌套的时候,可能还是会比较嘀咕, #define CONVERT ...