HDU 5988 Coding Contest(费用流+浮点数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5988

题目大意:

给定n个点,m条有向边,每个点是一个吃饭的地方,每个人一盒饭。每个点有S个人,有B盒饭。每条边只能被走c次,每条边上都有电线,
第一个人通过的时候,不会破坏电线,从第二个人开始,每次都有概率p破坏掉电线。使得每个人都能吃饭,求最小破坏电线的概率。

解题思路:

题目要求我们求最小破坏电线的概率,就是一个最小乘积问题,加上log可以将其转变为加法,那样就可以使用费用刘来解决了。

按以下方式建图:

①源点st向第i个人建边,流量为S。

②第i个人向汇点建边,流量为B。

③u->v连边,流量为c,花费为-log(1-p)。

然后跑费用流,1-exp(-cost)即为答案。

代码

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<queue>
  7 #include<vector>
  8 #define LL long long
  9 #define pii pair<double,int>
 10 #define pll pair<long long,long long>
 11 #define rep(i,a,b) for(int i=a;i<=b;i++)
 12 #define per(i,a,b) for(int i=a;i>=b;i--)
 13 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
 14 #define bug cout<<"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"<<endl;
 15 #define bugc(_) cout << (#_) << " = " << (_) << endl;
 16 using namespace std;
 17 const double eps=1e-8;
 18 const int N=1e2+5;
 19 const int M=1e5+5;
 20 const int INF=0x3f3f3f3f;
 21
 22 struct node{
 23     int to,next,flow;
 24     double cost;
 25 }edge[M*2];
 26
 27 int cnt,st,en,n,m;
 28 int head[N],pre[N];
 29 double dis[N];//dis[i]表示到dis[i]为止不破坏电线的最大概率
 30 bool vis[N];
 31
 32 int sgn(double x) { return x < -eps? -1: x > eps; }
 33
 34 void init(){
 35     cnt=2;
 36     memset(head,0,sizeof(head));
 37 }
 38
 39 void link(int u,int v,int flow,double cost){
 40     edge[cnt]=node{v,head[u],flow,cost};
 41     head[u]=cnt++;
 42     edge[cnt]=node{u,head[v],0,-cost};
 43     head[v]=cnt++;
 44 }
 45
 46 bool spfa() {
 47     memset(pre,0,sizeof(pre));
 48     memset(vis,false,sizeof(vis));
 49     for(int i=st;i<=en;i++) dis[i]=INF;
 50     dis[st]=0;
 51     queue<int>q;
 52     q.push(st);
 53     while(!q.empty()){
 54         int u=q.front();
 55         q.pop();
 56         vis[u]=false;
 57         for(int i=head[u];i;i=edge[i].next){
 58             node t=edge[i];
 59             if(t.flow&&dis[t.to]>dis[u]+t.cost+eps){
 60                 dis[t.to]=dis[u]+t.cost;
 61                 pre[t.to]=i;
 62                 if(!vis[t.to]){
 63                     vis[t.to]=true;
 64                     q.push(t.to);
 65                 }
 66             }
 67         }
 68     }
 69     if(dis[en]==INF)
 70         return false;
 71     return true;
 72 }
 73
 74 void mcmf(int &flow,double &cost){
 75     while(spfa()){
 76         int mmin=INF;
 77         for(int i=pre[en];i;i=pre[edge[i^1].to]){
 78             mmin=min(mmin,edge[i].flow);
 79         }
 80         for(int i=pre[en];i;i=pre[edge[i^1].to]){
 81             edge[i].flow-=mmin;
 82             edge[i^1].flow+=mmin;
 83             cost+=edge[i].cost*mmin;
 84         }
 85         flow+=mmin;
 86     }
 87 }
 88
 89 int main(){
 90     int T;
 91     scanf("%d",&T);
 92     while(T--){
 93         init();
 94         int n,m;
 95         scanf("%d%d",&n,&m);
 96         st=0,en=n+1;
 97         for(int i=1;i<=n;i++){
 98             int s,b;
 99             scanf("%d%d",&s,&b);
100             if(s-b>0) link(st,i,s-b,0);
101             if(s-b<0) link(i,en,b-s,0);
102         }
103         for(int i=1;i<=m;i++){
104             int u,v,flow;
105             double p;
106             scanf("%d%d%d%lf",&u,&v,&flow,&p);
107             p=-log(1-p);
108             if(flow>0) link(u,v,1,0);
109             if(flow>1) link(u,v,flow-1,p);
110         }
111         int flow=0;
112         double cost=0;
113         mcmf(flow,cost);
114         cost=exp(-cost);
115         printf("%.2f\n",1-cost);
116     }
117     return 0;
118 }

原文地址:https://www.cnblogs.com/fu3638/p/9897550.html

时间: 2024-10-08 09:20:58

HDU 5988 Coding Contest(费用流+浮点数)的相关文章

2016ACM/ICPC亚洲区青岛站 Coding Contest 费用流

目录 2016ACM/ICPC亚洲区青岛站 Coding Contest 费用流 题目描述 题意(博主的鬼畜翻译): 分析: 代码 2016ACM/ICPC亚洲区青岛站 Coding Contest 费用流 题目描述 题目描述 A coding contest will be held in this university, in a huge playground. The whole playground would be divided into N blocks, and there w

HDU 4067 Random Maze 费用流

Random Maze Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1114    Accepted Submission(s): 387 Problem Description In the game "A Chinese Ghost Story", there are many random mazes which h

POJ 2135 Farm Tour &amp;&amp; HDU 2686 Matrix &amp;&amp; HDU 3376 Matrix Again 费用流求来回最短路

累了就要写题解,最近总是被虐到没脾气. 来回最短路问题貌似也可以用DP来搞,不过拿费用流还是很方便的. 可以转化成求满流为2 的最小花费.一般做法为拆点,对于 i 拆为2*i 和 2*i+1,然后连一条流量为1(花费根据题意来定) 的边来控制每个点只能通过一次. 额外添加source和sink来控制满流为2. 代码都雷同,以HDU3376为例. #include <algorithm> #include <iostream> #include <cstring> #in

hdu 3315 My Brute 费用流,费用最小且代价最小

很常见的想法了= = #include <stdio.h> #include <iostream> #include <string.h> using namespace std; const int N=400; const int MAXE=200000; const int inf=1<<30; int head[N],s,t,cnt,n,m,ans; int d[N],pre[N]; bool vis[N]; int q[MAXE]; int V[N

HDU 3395 Special Fish(费用流)

题目地址:HDU 3395 刷了几道白书和CF上的非算法的智商题,感觉智商越来越接近负数了...还是先刷几道简单题缓缓.. 这题很简单,二分图模型,用费用流也可以,用KM也可以.不过需要注意的是这里是最大费用流,并不是最大费用最大流,区别在于是否是最大流,这题可以不是最大流,所以要当费用开始减少的时候停止继续流,来保证费用是最大的. 代码如下: #include <iostream> #include <cstdio> #include <string> #includ

HDU 4067 Random Maze 费用流 构造欧拉通路

题目链接:点击打开链接 题意: 给定n个点m条有向边的图, 起点s ,终点t 下面m条边 u,v, a,b  若选择这条边花费为a, 不选择花费为b 构造一条欧拉通路使得起点是s,终点是t,且花费最小. 思路: 首先能想到一个简单的思路:假设所有边都选择,然后在费用流里跑,就会出现负环的问题.. 所以为了避免负环,让所有费用都为正值: int sum = 0; 若a>b, 则 费用要为正只能是 a-b, 默认这条边是删除是, sum += b, 那么如果我们要选择这条边,则从u=>v, 费用为

HDU 2686 Matrix(最大费用流)

Matrix Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1890    Accepted Submission(s): 1005 Problem Description Yifenfei very like play a number game in the n*n Matrix. A positive integer numbe

HDU 3315 My Brute(费用流)

题目地址:HDU 3315 这个题的思路完全是自己想出来的,自我感觉挺巧妙的...(大牛勿喷...)对大胆建图又多了一份信心. 具体思路是构造一个二分图,Si连源点,Xi连汇点,流量都是1,费用0.然后当Si可以赢Xj的时候,就对这两人连一条边,费用值为-Vi*1000,如果i==j的话,费用值就再减1,因为题目要求尽量不改变原先的顺序,所以说应该尽量让序号相同的对打.而费用值减1的话,会优先考虑序号相同的,而且让费用扩大了1000倍,此时也不会改变主要的分数因素大小.同理,输的话,费用值为Vi

HDU 2686 Matrix(最大费用最大流+拆点)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2686 和POJ3422一样 删掉K把汇点与源点的容量改为2(因为有两个方向的选择)即可 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> const int ma