HDU–5988-Coding Contest(最小费用最大流变形)
Coding Contest
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2653 Accepted Submission(s): 579
Problem Description
A coding contest will be held in this university, in a huge playground. The whole playground would be divided into N blocks, and there would be M directed paths linking these blocks. The i-th path goes from the ui-th block to the vi-th block. Your task is to solve the lunch issue. According to the arrangement, there are si competitors in the i-th block. Limited to the size of table, bi bags of lunch including breads, sausages and milk would be put in the i-th block. As a result, some competitors need to move to another block to access lunch. However, the playground is temporary, as a result there would be so many wires on the path.
For the i-th path, the wires have been stabilized at first and the first competitor who walker through it would not break the wires. Since then, however, when a person go through the i - th path, there is a chance of pi to touch
the wires and affect the whole networks. Moreover, to protect these wires, no more than ci competitors are allowed to walk through the i-th path.
Now you need to find a way for all competitors to get their lunch, and minimize the possibility of network crashing.
Input
The first line of input contains an integer t which is the number of test cases. Then t test cases follow.
For each test case, the first line consists of two integers N (N ≤ 100) and M (M ≤ 5000). Each of the next N lines contains two integers si and bi (si , bi ≤ 200).
Each of the next M lines contains three integers ui , vi and ci(ci ≤ 100) and a float-point number pi(0 < pi < 1).
It is guaranteed that there is at least one way to let every competitor has lunch.
Output
For each turn of each case, output the minimum possibility that the networks would break down. Round it to 2 digits.
Sample Input
1
4 4
2 0
0 3
3 0
0 3
1 2 5 0.5
3 2 5 0.5
1 4 5 0.5
3 4 5 0.5
Sample Output
0.50 思路: 这是一个最小费用最大流的变形题目。 要仔细读懂题目,题目要求的是崩溃的最小可能性。由于崩溃可能是由一条边或多条边一起的,所以正着求崩溃概率很难求,我们反着思考,用1去减每条边都不引起图崩溃的概率即为崩溃的概率。 由于求的是最小,而且边有容量限制,我们很自然的想到了最小费用最大流(对于不崩溃的概率应该是最大费用最大流) 建图时,某个点有人则想s连一条容量为人数的边,有食物则向t连一条容量为是无数的边,其他的边按照题目的数据相连即可,这个很好处理。 还有一个条件是某条路第一遍走的时候是没有花费的。我的处理方法是将一条容量为c,花费为w的边拆成两条边:容量为c-1,花费为w的一条边;容量为1,花费为1.0的一条边(花费为1.0是为了确保不会对最终结果产生影响)。 细节很多,由于概率要想乘所以初始化时要注意,算一条增广路径对总结果的贡献时也要注意是乘方而不是简单的相乘。 代码1:求增广路径时直接求最长路
1 /*
2 * @FileName: D:\代码与算法\2017训练比赛\2016青岛区域赛\g.cpp
3 * @Author: Pic
4 * @Created Time: 2017/10/7 12:46:48
5 */
6 #include <bits/stdc++.h>
7 using namespace std;
8 const double INF = -1*10.0;
9 const int maxn=200+10;
10
11 struct Edge
12 {
13 int from,to,cap,flow;
14 double cost;
15 Edge(){}
16 Edge(int f,int t,int c,int fl,double co):from(f),to(t),cap(c),flow(fl),cost(co){}
17 };
18
19 struct MCMF
20 {
21 int n,m,s,t;
22 vector<Edge> edges;
23 vector<int> G[maxn];
24 bool inq[maxn]; //是否在队列
25 double d[maxn]; //Bellman_ford单源最短路径
26 int p[maxn]; //p[i]表从s到i的最小费用路径上的最后一条弧编号
27 int a[maxn]; //a[i]表示从s到i的最小残量
28
29 //初始化
30 void init(int n,int s,int t)
31 {
32 this->n=n, this->s=s, this->t=t;
33 edges.clear();
34 for(int i=0;i<n;++i) G[i].clear();
35 }
36
37 //添加一条有向边
38 void AddEdge(int from,int to,int cap,double cost)
39 {
40 edges.push_back(Edge(from,to,cap,0,cost));
41 edges.push_back(Edge(to,from,0,0,-cost));
42 m=edges.size();
43 G[from].push_back(m-2);
44 G[to].push_back(m-1);
45 }
46
47 //求一次增广路
48 bool BellmanFord(int &flow, double &cost)
49 {
50 for(int i=0;i<n;++i) d[i]=INF;
51 memset(inq,0,sizeof(inq));
52 d[s]=1.0, a[s]=1e9+30, inq[s]=true, p[s]=0;
53 queue<int> Q;
54 Q.push(s);
55 while(!Q.empty())
56 {
57 //cout<<"Q"<<endl;
58 int u=Q.front(); Q.pop();
59 inq[u]=false;
60 for(int i=0;i<G[u].size();++i)
61 {
62 Edge &e=edges[G[u][i]];
63 double tmp=(d[u]*e.cost);
64 //tmp=-1*fabs(tmp);
65 if( e.cap>e.flow && d[e.to] < tmp )
66 {
67 d[e.to]=tmp;
68 p[e.to]=G[u][i];
69 a[e.to]= min(a[u],e.cap-e.flow);
70 if(!inq[e.to]){ Q.push(e.to); inq[e.to]=true; }
71 }
72 }
73 }
74 //cout<<d[t]<<endl;
75 //if(fabs(d[t]-INF)<1e-3) return false;
76 if(d[t]<0) return false;
77 flow += a[t];
78 for(int i=0;i<a[t];i++) cost*=(d[t]);
79 int u=t;
80 while(u!=s)
81 {
82 edges[p[u]].flow += a[t];
83 edges[p[u]^1].flow -=a[t];
84 u = edges[p[u]].from;
85 }
86 return true;
87 }
88
89 //求出最小费用最大流
90 double Min_cost()
91 {
92 int flow=0;double cost=1.0;
93 while(BellmanFord(flow,cost)) ;
94 return cost;
95 }
96 }MM;
97 int main()
98 {
99 // freopen("data.in","r",stdin);
100 //freopen("data.out","w",stdout);
101 int t;
102 scanf("%d",&t);
103 while(t--){
104 int n,m;
105 scanf("%d%d",&n,&m);
106 MM.init(n+2,0,n+1);
107 int x,y;
108 for(int i=1;i<=n;i++){
109 scanf("%d%d",&x,&y);
110 if(x!=0)
111 MM.AddEdge(0,i,x,1.0);
112 if(y!=0)
113 MM.AddEdge(i,n+1,y,1.0);
114 }
115 int u,v,c;double w;
116 for(int i=1;i<=m;i++){
117 scanf("%d%d%d%lf",&u,&v,&c,&w);
118 //MM.AddEdge(u,v,c,w);
119 if(c>0){
120 MM.AddEdge(u,v,c-1,1.0-w);
121 MM.AddEdge(u,v,1,1.0);
122 }
123 }
124 double res=fabs(MM.Min_cost());
125 //cout<<res<<endl;
126 res=1.0-res;
127 if(res>=1.0) res=1.0;
128 printf("%.2lf\n",res);
129 }
130 return 0;
131 }代码2:花费取负,求最小费用最大流,注意初始化的值
1 /*
2 * @FileName: D:\代码与算法\2017训练比赛\2016青岛区域赛\g.cpp
3 * @Author: Pic
4 * @Created Time: 2017/10/7 12:46:48
5 */
6 #include <bits/stdc++.h>
7 using namespace std;
8 const double INF = 1e8;
9 const int maxn=200+10;
10
11 struct Edge
12 {
13 int from,to,cap,flow;
14 double cost;
15 Edge(){}
16 Edge(int f,int t,int c,int fl,double co):from(f),to(t),cap(c),flow(fl),cost(co){}
17 };
18
19 struct MCMF
20 {
21 int n,m,s,t;
22 vector<Edge> edges;
23 vector<int> G[maxn];
24 bool inq[maxn]; //是否在队列
25 double d[maxn]; //Bellman_ford单源最短路径
26 int p[maxn]; //p[i]表从s到i的最小费用路径上的最后一条弧编号
27 int a[maxn]; //a[i]表示从s到i的最小残量
28
29 //初始化
30 void init(int n,int s,int t)
31 {
32 this->n=n, this->s=s, this->t=t;
33 edges.clear();
34 for(int i=0;i<n;++i) G[i].clear();
35 }
36
37 //添加一条有向边
38 void AddEdge(int from,int to,int cap,double cost)
39 {
40 edges.push_back(Edge(from,to,cap,0,cost));
41 edges.push_back(Edge(to,from,0,0,-cost));
42 m=edges.size();
43 G[from].push_back(m-2);
44 G[to].push_back(m-1);
45 }
46
47 //求一次增广路
48 bool BellmanFord(int &flow, double &cost)
49 {
50 for(int i=0;i<n;++i) d[i]=INF;
51 memset(inq,0,sizeof(inq));
52 d[s]=1.0, a[s]=INF, inq[s]=true, p[s]=0;
53 queue<int> Q;
54 Q.push(s);
55 while(!Q.empty())
56 {
57 // cout<<"Q"<<endl;
58 int u=Q.front(); Q.pop();
59 inq[u]=false;
60 for(int i=0;i<G[u].size();++i)
61 {
62 Edge &e=edges[G[u][i]];
63 double tmp=(d[u]*e.cost);
64 tmp=-1*fabs(tmp);
65 if( e.cap>e.flow && d[e.to] > tmp )
66 {
67 d[e.to]=tmp;
68 p[e.to]=G[u][i];
69 a[e.to]= min(a[u],e.cap-e.flow);
70 if(!inq[e.to]){ Q.push(e.to); inq[e.to]=true; }
71 }
72 }
73 }
74 if(fabs(d[t]-INF)<1e3) return false;
75 flow += a[t];
76 for(int i=0;i<a[t];i++) cost*=(d[t]);
77 int u=t;
78 while(u!=s)
79 {
80 edges[p[u]].flow += a[t];
81 edges[p[u]^1].flow -=a[t];
82 u = edges[p[u]].from;
83 }
84 return true;
85 }
86
87 //求出最小费用最大流
88 double Min_cost()
89 {
90 int flow=0;double cost=1.0;
91 while(BellmanFord(flow,cost));
92 return cost;
93 }
94 }MM;
95 int main()
96 {
97 // freopen("data.in","r",stdin);
98 //freopen("data.out","w",stdout);
99 int t;
100 scanf("%d",&t);
101 while(t--){
102 int n,m;
103 scanf("%d%d",&n,&m);
104 MM.init(n+2,0,n+1);
105 int x,y;
106 for(int i=1;i<=n;i++){
107 scanf("%d%d",&x,&y);
108 if(x!=0)
109 MM.AddEdge(0,i,x,1.0);
110 if(y!=0)
111 MM.AddEdge(i,n+1,y,1.0);
112 }
113 int u,v,c;double w;
114 for(int i=1;i<=m;i++){
115 scanf("%d%d%d%lf",&u,&v,&c,&w);
116 //MM.AddEdge(u,v,c,w);
117 if(c>0){
118 MM.AddEdge(u,v,c-1,w-1.0);
119 MM.AddEdge(u,v,1,1.0);
120 }
121 }
122 double res=fabs(MM.Min_cost());
123 //cout<<res<<endl;
124 res=1.0-res;
125 if(res>=1.0) res=1.0;
126 printf("%.2lf\n",res);
127 }
128 return 0;
129 }
HDU–5988-Coding Contest(最小费用最大流变形)的更多相关文章
- HDU 5988 Coding Contest(最小费用最大流变形)
Problem DescriptionA coding contest will be held in this university, in a huge playground. The whole ...
- HDU 5988.Coding Contest 最小费用最大流
Coding Contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- HDU5988/nowcoder 207G - Coding Contest - [最小费用最大流]
题目链接:https://www.nowcoder.com/acm/contest/207/G 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5988 ...
- hdu 1533 Going Home 最小费用最大流
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1533 On a grid map there are n little men and n house ...
- hdu 3667(拆边+最小费用最大流)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3667 思路:由于花费的计算方法是a*x*x,因此必须拆边,使得最小费用流模板可用,即变成a*x的形式. ...
- hdu 3488(KM算法||最小费用最大流)
Tour Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)Total Submis ...
- hdu 3395(KM算法||最小费用最大流(第二种超级巧妙))
Special Fish Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- hdu 1533 Going Home 最小费用最大流 入门题
Going Home Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tota ...
- POJ 2195 & HDU 1533 Going Home(最小费用最大流)
这就是一道最小费用最大流问题 最大流就体现到每一个'm'都能找到一个'H',但是要在这个基础上面加一个费用,按照题意费用就是(横坐标之差的绝对值加上纵坐标之差的绝对值) 然后最小费用最大流模板就是再用 ...
随机推荐
- MQTT协议探究(三)
1 回顾与本次目标 1.1 回顾 主题通配符 主题语义和用法 WireShark进行抓包分析了报文 报文分析: SUBSCRIBE--订阅主题 SUBACK--订阅确认 UNNSUBSCRIBE--取 ...
- async/await 的引用
static async void Start() { string s = "ass"; Console.WriteLine(getMemory(s)+"Hello W ...
- 1、windows安装npm教程 --参考自https://www.cnblogs.com/jianguo221/p/11487532.html
windows安装npm教程 1.在使用之前,先类掌握3个东西,明白它们是用来干什么的: npm: nodejs 下的包管理器. webpack: 它主要用途是通过CommonJS 的语法把所有 ...
- [NOIP2018模拟赛10.16]手残报告
[NOIP2018模拟赛10.16]手残报告 闲扯 炉石乱斗模式美滋滋啊,又颓到好晚... 上来T2先敲了树剖,看T1发现是个思博DP,然后没过大样例,写个暴力发现还是没过大样例!?才发现理解错题意了 ...
- win10下 安装迅雷精简版
下载链接:https://files-cdn.cnblogs.com/files/del88/ThunderMini_1.5.3.288.zip 他妈的 今天安装迅雷精简版 在win10上 竟然报错, ...
- identity server4获取token和userInfo
一.简介 IdentityServer4(ids4)是用于ASP.NET Core的OpenID Connect和OAuth 2.0框架.在许多成熟的.net core框架中都完美的集成的该身份服务框 ...
- python+Appium自动化:TouchAction九宫格实战
TouchAction Touch Action包含一系列操作,比如按压.长按.点击.移动.暂停. 使用TochAction需要先导入对应的模块 from appium.webdriver.commo ...
- CodeForces - 113B Petr# (后缀数组)
应该算是远古时期的一道题了吧,不过感觉挺经典的. 题意是给出三一个字符串s,a,b,求以a开头b结尾的本质不同的字符串数. 由于n不算大,用hash就可以搞,不过这道题是存在复杂度$O(nlogn)$ ...
- Python 列表和元组 (2) 持续更新
数据结构就是数据的集合.Python最基本的数据结构就是序列,每个元素都会被分配一个元素的位置,也可以称为索引.注意索引都是从0开始的. Python包含6种内建的序列,分别是列表.元组.字符串.Un ...
- mongodb命令---花样查询语句
闲言少叙 查出价格低于200的商品信息----包含商品名称,货物编号,价格,添加信息等 db.goods.find( {}}, {,,,} ) 商品分类不为3的商品 db.goods.find( {} ...