Coding Contest HDU - 5988(费用流)
题意:
有n个区域和m条路,每个区域有a[i]个人和b[i]个食物,然后是m条路连接两个区域,这条路容量为cap,这条路断掉的概率为p,第一个经过的时候一定不会断,后面的人有概率p会断,现在需要所有人都吃上饭并且破坏网络的概率最小
解析:
多源多汇,建一个超级源指向食物多的 超级汇指向人多的 概率为价值 板子里的价值都是加 所以化成log形式就好了 最后在化回来
求的是最小被破坏的概率,那么1 - 最大被破坏的概率就好了 费用流是价值最小 给价值加个符号 不就是最大了嘛
代码来自 :https://blog.csdn.net/Nemaleswang/article/details/77870967
改成了我喜欢写的形式,为什么不贴我的。。。。。emm。。。明明写的好看。。。为啥我的T
生活失去了希望
#include <map> #include <set> #include <cmath> #include <queue> #include <stack> #include <vector> #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 205; const int MaxEdge = 40005; const double eps = 1e-8; int max_flow; double value; struct Edge{ int to,vol,next; double cost; }Node[MaxEdge]; int Pre[maxn],Path[maxn],Head[maxn],cnt, f[maxn]; double Dist[maxn]; bool vis[maxn]; void addedge(int u, int v, int vol, double cost){ Node[cnt].to = v; Node[cnt].vol = vol; Node[cnt].cost = cost; Node[cnt].next = Head[u]; Head[u] = cnt++; Node[cnt].to = u; Node[cnt].vol = 0; Node[cnt].cost = -cost; Node[cnt].next = Head[v]; Head[v] = cnt++; } bool Spfa(int s, int t){ for(int i = 0;i < maxn;i++) Dist[i] = INF*1.0; memset(Pre, -1, sizeof(Pre)); memset(vis, false, sizeof(vis)); Dist[s] = 0.0; queue<int>Q; vis[s] = true; Q.push(s); f[s] = INF; while (!Q.empty()){ int u = Q.front(); Q.pop(); vis[u] = false; for (int e = Head[u]; e != -1; e = Node[e].next){ int v = Node[e].to; if (Node[e].vol > 0 && Dist[v] - Dist[u] - Node[e].cost > eps){ Dist[v] = Dist[u] + Node[e].cost; Pre[v] = u; Path[v] = e; f[Node[e].to] = min(f[u], Node[e].vol); if(!vis[v]){ vis[v] = true; Q.push(v); } } } } if(Pre[t] == -1) return 0; int u, v, e; for(u = t; u != s; u = Pre[u]){ e = Path[u]; Node[e].vol -= f[t]; Node[e^1].vol += f[t]; } max_flow += f[t]; value += (double)f[t]*Dist[t]; return 1; } void MCMF(int s, int t) { max_flow = 0; value = 0; while(Spfa(s, t)); } void init(){ memset(Head,-1,sizeof(Head)); cnt = 0; } int main(){ int t,n,m,a[maxn],b[maxn],c[maxn]; int u,v,cap; double p; scanf("%d",&t); while(t--){ init(); scanf("%d%d",&n,&m); for(int i = 1;i <= n;i++){ scanf("%d%d",&a[i],&b[i]); c[i] = a[i]-b[i]; } while(m--){ scanf("%d%d%d%lf",&u,&v,&cap,&p); p = -log2(1.0-p); if(cap > 0) addedge(u,v,1,0.0); if(cap-1 > 0) addedge(u,v,cap-1,p); } for(int i = 1;i <= n;i++){ if(c[i] > 0) addedge(0,i,c[i],0.0); else if(c[i] < 0) addedge(i,n+1,-c[i],0.0); } MCMF(0,n+1); double ans = pow(2,-value); printf("%.2f\n",1.0-ans); } return 0; }
自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。