有下界的最小费用可行流(bzoj 3876: [Ahoi2014]支线剧情)
来源:互联网 发布:c语言入门知识 编辑:程序博客网 时间:2024/05/19 12:16
什么是有下界的最小费用可行流?
平时来讲都是最小费用最大流,也就是在满流的前提条件下费用尽可能的少,而最小费用可行流一般不要求满流,但是每条边都有最小流量要求(比如经过边e(u,v)的流量不能少于4等等),而你只要满足所有边的最小流量要求就好,在这种情况下求出最小费用
无源汇点的网络:所有点都满足流量平衡
有源汇点的网络:除了源汇点外都满足流量平衡,源点只有流出,汇点只有流入
如何解决这类问题?
当然是将它转成最小费用最大流就好了!
那么怎么转?
先分类:
对于1:无源点汇点求网络可行流
①增加新源点和新汇点
②对于点u,设u所有流出边的下界和为otu,所有流入u的边的下界和为inu,令x=inu-otu,如果x<0,那么从u向汇点连接一条流量为|x|的边,如果x>0,那么从源点向u连接一条流量为x的边
之后求最小费用最大流,如果无法满流,则说明原题根本没有可行流
对于2:有源点汇点的网络可行流
很好办,只要从汇点向源点连一条容量为无穷大且无下界的边,就成第一种情况了
附录:其实以上都是求有下界的最小费用可行流,并没有要求最大流或者最小流
如果有要求的话难度就更高一级别,就先不讲了,分享一个链接
http://blog.csdn.net/water_glass/article/details/6823741
3876: [Ahoi2014]支线剧情
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1811 Solved: 1089
[Submit][Status][Discuss]
Description
Input
Output
输出一行包含一个整数,表示JYY看完所有支线剧情所需要的最少时间。
Sample Input
Sample Output
这题就是给你一个有向无环联通图,除此之外每个点都可以瞬间回到点1,并且1的拓扑序最高
求每条边都经过至少一次的最短总耗时
因为每条边都至少经过一次,那么相当于每条边的下界流量就为1,上届显然无穷大
费用就是这条边的长度,那么就好办了
新建源点汇点
①如果x到y有条长度为z的边,那么x到y连接一条流量inf,费用为z的边(每条边除了必走的1次外可以无限走)
②所有点向点1连接一条流量inf,费用为0的边(因为你可以随时重新开始游戏)
③所有点向汇点连接一条流量为该点出度,费用为0的边
(因为所有边都要至少经过1次,那么对于x点必须要准备好out[x]的流量才行)
④源点向所有点连接一条流量为该点入度,费用为0的边
根据题意一定可行,直接套最小费用最大流模板就好了
注意最后答案加上所有路径的长度,因为每条边必走一次而你算出的费用不包括必走的那一次
(按道理从源点到所有点的边应该是有费用的,源点到x的费用为x所有入边的长度之和,可是这步麻烦省掉了)
204ms
#include<stdio.h>#include<queue>#include<string.h>using namespace std;#define LL long long#define inf 1044266558typedef struct Res{int next;int to, from;int flow, cost;}Road;Road G[90005];int head[505], vis[505], dis[505], in[505], out[505], S, T, cnt, ans; void Add(int u, int v, int flow, int cost){cnt++;G[cnt].next = head[u];head[u] = cnt;G[cnt].from = u;G[cnt].to = v;G[cnt].flow = flow;G[cnt].cost = cost;}int SPFA(){int now, i, v;queue<int> q;memset(vis, 0, sizeof(vis));memset(dis, 62, sizeof(dis));q.push(S);vis[S] = 1;dis[S] = 0;while(q.empty()==0){now = q.front();q.pop();vis[now] = 0;for(i=head[now];i!=0;i=G[i].next){v = G[i].to;if(G[i].flow && dis[v]>dis[now]+G[i].cost){dis[v] = dis[now]+G[i].cost;if(vis[v]==0){vis[v] = 1,q.push(v);}}}}if(dis[T]<15000000)return 1;return 0;}int Sech(int now, int low){int i, w, used;vis[now] = 1;if(now==T)return low;used = low;for(i=head[now];i!=0;i=G[i].next){if(G[i].flow && dis[G[i].to]==dis[now]+G[i].cost && vis[G[i].to]==0){w = Sech(G[i].to, min(used, G[i].flow));G[i].flow -= w;G[i^1].flow += w;used -= w;ans += w*G[i].cost;if(used==0)return low;}}return low-used; }int main(void){int i, j, n, x, y;while(scanf("%d", &n)!=EOF){S = n+2, T = n+1;cnt = 1, ans = 0;memset(in, 0, sizeof(in));memset(out, 0, sizeof(out));for(i=2;i<=n;i++){Add(i, 1, inf, 0);Add(1, i, 0, 0);}for(i=1;i<=n;i++){scanf("%d", &out[i]);for(j=1;j<=out[i];j++){scanf("%d%d", &x, &y);Add(i, x, inf, y);Add(x, i, 0, -y);in[x]++;ans += y;}}for(i=1;i<=n;i++){x = in[i]-out[i];if(x<0){Add(i, T, -x, 0);Add(T, i, 0, 0);}else{Add(S, i, x, 0);Add(i, S, 0, 0);}}while(SPFA()) {memset(vis, 0, sizeof(vis));while(Sech(S, 1044266558))memset(vis, 0, sizeof(vis));}printf("%d\n", ans);}return 0;}
- 有下界的最小费用可行流(bzoj 3876: [Ahoi2014]支线剧情)
- bzoj 3876 [Ahoi2014]支线剧情(有上下界的最小费用流)
- BZOJ 3876([Ahoi2014]支线剧情-带下界的最小费用可行流)
- [上下界有源汇最小费用可行流] BZOJ 3876: [Ahoi2014&Jsoi2014]支线剧情
- [BZOJ3876][AHOI2014]支线剧情-有下界的最小费用流
- bzoj 3876: [Ahoi2014]支线剧情 (有上下界的费用流)
- 3876: [Ahoi2014]支线剧情|有上下界的费用流
- 3876: [Ahoi2014]支线剧情 有上下界的费用流
- [AHOI2014]支线剧情(有上下界的费用流)
- BZOJ 3876: [Ahoi2014]支线剧情(有源有汇有下界的费用流)
- [上下界费用流] BZOJ 3876 [Ahoi2014]支线剧情
- BZOJ 3876: [Ahoi2014]支线剧情【下界费用流
- 【bzoj3876】[Ahoi2014]支线剧情 有上下界的费用流
- 【bzoj3876】【AHOI2014】【支线剧情】【有上下界的费用流】
- bzoj 3876: [Ahoi2014]支线剧情 (无源汇最小费用可行流)[省选计划系列]
- 【有上下界网络流+费用流多路增广】【bzoj 3876】: [Ahoi2014]支线剧情
- 【BZOJ3876】【Ahoi2014】支线剧情 有下界的最小费用最大流
- bzoj3876[AHOI2014]支线剧情(有上下界的费用流)
- Eclipse添加Spket插件实现ExtJs智能提示
- JAVA语言与C++相比优劣势分析
- 关于STM中SPI运用的NSS引脚解读
- nslookup命令详解
- Javascript中的高阶函数介绍
- 有下界的最小费用可行流(bzoj 3876: [Ahoi2014]支线剧情)
- 垃圾收集算法、垃圾回收算法、java垃圾收集器
- js上传图片前预览
- C#监控类属性的更改(大花猫动了哪些小玩具)
- docker中tomcat镜像的使用
- HDU 6055 Regular polygon
- mosquitto鉴权插件的开发与说明(一)
- ORA-28040: No matching authentication protocol 解决
- C#事件与委托详解