【HDU5988】Coding Contest 费用流

2024-04-13 12:48
文章标签 费用 coding contest hdu5988

本文主要是介绍【HDU5988】Coding Contest 费用流,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

传送⻔

题意

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

分析

一开始想的是网络流,不太敢确定

我们求最小破坏电线的概率,就是求1 - 最不破坏电线的概率,我们把每天边权改成1 - p i p_i pi,然后考虑用网络流解决这个问题
但是网络流的费用是相加的,这里的概率显然要乘,怎么处理呢,考虑把费用 l o g log log处理,就可以把相加转化成相乘了
需要注意的是,用 s p f a spfa spfa求最小费用流的话,需要判 e p s eps eps,否则会疯狂 t t t

代码

#pragma GCC optimize(3)
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
#define _CRT_SECURE_NO_WARNINGS
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
typedef vector<int> VI;
const int INF = 0x3f3f3f3f;
const int N = 5e3 + 10,M = 1e5 + 10;
const ll mod = 1000000007;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a) {char c = getchar(); T x = 0, f = 1; while (!isdigit(c)) {if (c == '-')f = -1; c = getchar();}while (isdigit(c)) {x = (x << 1) + (x << 3) + c - '0'; c = getchar();} a = f * x;
}
int gcd(int a, int b) {return (b > 0) ? gcd(b, a % b) : a;}
int h[N],ne[M],e[M],idx;
double w[M],d[N],f[M],incf[N];
int n,m,S,T;
int q[N],pre[N];
bool st[N];void add(int a,int b,double c,double d){ne[idx] = h[a],e[idx] = b,f[idx] = c,w[idx] = d,h[a] = idx++;ne[idx] = h[b],e[idx] = a,f[idx] = 0,w[idx] = -d,h[b] = idx++;
}bool spfa(){int hh = 0,tt = 1;for(int i = 0;i <= n + 10;i++) d[i] = INF,incf[i] = 0;q[0] = S,d[S] = 0,incf[S] = INF;while(hh != tt){int t = q[hh++];if(hh == N) hh = 0;st[t] = false;for(int i = h[t];~i;i = ne[i]){int ver = e[i]; if(f[i] && d[ver] - d[t] - w[i] > eps){pre[ver] = i;d[ver] = d[t] + w[i];incf[ver] = min(f[i],incf[t]);if(!st[ver]){q[tt++] = ver;if(tt == N) tt = 0;st[ver] = true;}}}}return incf[T] > 0;
}void EK(int &flow,double &cost){flow = cost = 0;while(spfa()){double t = incf[T];flow += t,cost += t * d[T];for(int i = T;i != S;i = e[pre[i] ^ 1]){f[pre[i]] -= t;f[pre[i] ^ 1] += t;}}
}void init(){scanf("%d%d",&n,&m);idx = 0;for(int i = 0;i <= n + 10;i++) h[i] = -1;S = 0,T = n + 1;for(int i = 1;i <= n;i++){int x,y;scanf("%d%d",&x,&y);add(S,i,x,0),add(i,T,y,0);}while(m--){int x,y,z;double dis;scanf("%d%d%d%lf",&x,&y,&z,&dis);dis = -log(1.0 - dis);add(x,y,1,0);if(z > 1) {add(x,y,z - 1,dis);}}
}int main() {int T;scanf("%d",&T);while(T--){init();int flow;double ans;EK(flow,ans);ans = 1.0 - exp(-ans);printf("%.2lf\n",ans);}
}

这篇关于【HDU5988】Coding Contest 费用流的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/900178

相关文章

poj 2175 最小费用最大流TLE

题意: 一条街上有n个大楼,坐标为xi,yi,bi个人在里面工作。 然后防空洞的坐标为pj,qj,可以容纳cj个人。 从大楼i中的人到防空洞j去避难所需的时间为 abs(xi - pi) + (yi - qi) + 1。 现在设计了一个避难计划,指定从大楼i到防空洞j避难的人数 eij。 判断如果按照原计划进行,所有人避难所用的时间总和是不是最小的。 若是,输出“OPETIMAL",若

poj 2135 有流量限制的最小费用最大流

题意: 农场里有n块地,其中约翰的家在1号地,二n号地有个很大的仓库。 农场有M条道路(双向),道路i连接着ai号地和bi号地,长度为ci。 约翰希望按照从家里出发,经过若干块地后到达仓库,然后再返回家中的顺序带朋友参观。 如果要求往返不能经过同一条路两次,求参观路线总长度的最小值。 解析: 如果只考虑去或者回的情况,问题只不过是无向图中两点之间的最短路问题。 但是现在要去要回

poj 3422 有流量限制的最小费用流 反用求最大 + 拆点

题意: 给一个n*n(50 * 50) 的数字迷宫,从左上点开始走,走到右下点。 每次只能往右移一格,或者往下移一格。 每个格子,第一次到达时可以获得格子对应的数字作为奖励,再次到达则没有奖励。 问走k次这个迷宫,最大能获得多少奖励。 解析: 拆点,拿样例来说明: 3 2 1 2 3 0 2 1 1 4 2 3*3的数字迷宫,走两次最大能获得多少奖励。 将每个点拆成两个

poj 2195 bfs+有流量限制的最小费用流

题意: 给一张n * m(100 * 100)的图,图中” . " 代表空地, “ M ” 代表人, “ H ” 代表家。 现在,要你安排每个人从他所在的地方移动到家里,每移动一格的消耗是1,求最小的消耗。 人可以移动到家的那一格但是不进去。 解析: 先用bfs搞出每个M与每个H的距离。 然后就是网络流的建图过程了,先抽象出源点s和汇点t。 令源点与每个人相连,容量为1,费用为

poj 3068 有流量限制的最小费用网络流

题意: m条有向边连接了n个仓库,每条边都有一定费用。 将两种危险品从0运到n-1,除了起点和终点外,危险品不能放在一起,也不能走相同的路径。 求最小的费用是多少。 解析: 抽象出一个源点s一个汇点t,源点与0相连,费用为0,容量为2。 汇点与n - 1相连,费用为0,容量为2。 每条边之间也相连,费用为每条边的费用,容量为1。 建图完毕之后,求一条流量为2的最小费用流就行了

最大流、 最小费用最大流终极版模板

最大流  const int inf = 1000000000 ;const int maxn = 20000 , maxm = 500000 ;struct Edge{int v , f ,next ;Edge(){}Edge(int _v , int _f , int _next):v(_v) ,f(_f),next(_next){}};int sourse , mee

cf 164 C 费用流

给你n个任务,k个机器,n个任务的起始时间,持续时间,完成任务的获利 每个机器可以完成任何一项任务,但是同一时刻只能完成一项任务,一旦某台机器在完成某项任务时,直到任务结束,这台机器都不能去做其他任务 最后问你当获利最大时,应该安排那些机器工作,即输出方案 具体建图方法: 新建源汇S T‘ 对任务按照起始时间s按升序排序 拆点: u 向 u'连一条边 容量为 1 费用为 -c,

2014 Multi-University Training Contest 8小记

1002 计算几何 最大的速度才可能拥有无限的面积。 最大的速度的点 求凸包, 凸包上的点( 注意不是端点 ) 才拥有无限的面积 注意 :  凸包上如果有重点则不满足。 另外最大的速度为0也不行的。 int cmp(double x){if(fabs(x) < 1e-8) return 0 ;if(x > 0) return 1 ;return -1 ;}struct poin

2014 Multi-University Training Contest 7小记

1003   数学 , 先暴力再解方程。 在b进制下是个2 , 3 位数的 大概是10000进制以上 。这部分解方程 2-10000 直接暴力 typedef long long LL ;LL n ;int ok(int b){LL m = n ;int c ;while(m){c = m % b ;if(c == 3 || c == 4 || c == 5 ||

2014 Multi-University Training Contest 6小记

1003  贪心 对于111...10....000 这样的序列,  a 为1的个数,b为0的个数,易得当 x= a / (a + b) 时 f最小。 讲串分成若干段  1..10..0   ,  1..10..0 ,  要满足x非递减 。  对于 xi > xi+1  这样的合并 即可。 const int maxn = 100008 ;struct Node{int