hdu5988(最小費用流浮點)
阿新 • • 發佈:2018-11-16
題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=5988
思路:求網路最小破壞可能,就是求最大不破壞的可能,再加上一個負號又變成了求最小費用流,對於乘法加上一個對數就變成了加法,需要注意的是對於浮點數要加上eps。
#pragma GCC optimize(2) #include <cstdio> #include <cstdlib> #include <cstring> #include <bitset> #include <cmath> #include <cctype> #include <iostream> #include <algorithm> #include <string> #include <vector> #include <queue> #include <map> #include <set> #include <sstream> #include <iomanip> using namespace std; typedef long long ll; typedef unsigned long long ull; const ll inff = 0x3f3f3f3f3f3f3f3f; #define FOR(i,a,b) for(int i(a);i<=(b);++i) #define FOL(i,a,b) for(int i(a);i>=(b);--i) #define REW(a,b) memset(a,b,sizeof(a)) #define inf int(0x3f3f3f3f) #define si(a) scanf("%d",&a) #define sl(a) scanf("%lld",&a) #define sd(a) scanf("%lf",&a) #define ss(a) scanf("%s",a) #define mod ll(6666666) #define pb push_back #define eps 1e-6 #define lc d<<1 #define rc d<<1|1 #define Pll pair<ll,ll> #define P pair<int,int> #define pi acos(-1) const int N=1e2+7; struct edge{int to,cap; double cost; int rev;}; vector<edge>g[N]; int pre[N],prv[N],n,m,s,t,flow; double d[N],h[N],res; void add(int from,int to,int cap,double cost) { g[from].pb(edge{to,cap,cost,(int)g[to].size()}); g[to].pb(edge{from,0,-cost,(int)g[from].size()-1}); } void slove(int s,int t,int f,int n) { //int res=0; fill(h,h+n+1,0); while(f>0) { priority_queue<pair<double,int>,vector<pair<double,int>>,greater<pair<double,int>> > q; fill(d,d+n+1,inf); d[s]=0; q.push(pair<double,int>(0,s)); while(!q.empty()) { P p=q.top();q.pop(); int v=p.second; if(d[v]<p.first) continue; for(int i=0;i<(int)g[v].size();i++) { edge &e=g[v][i]; if(e.cap>0&&d[e.to]>d[v]+e.cost+h[v]-h[e.to]+eps) { d[e.to]=d[v]+e.cost+h[v]-h[e.to]; prv[e.to]=v;pre[e.to]=i; q.push(pair<double,int>(d[e.to],e.to)); } } } if(d[t]==inf) break; FOR(i,0,n) h[i]+=d[i]; int d=f; for(int i=t;i!=s;i=prv[i]) d=min(d,g[prv[i]][pre[i]].cap); f-=d,flow+=d; res+=d*h[t]; for(int i=t;i!=s;i=prv[i]) { edge &e=g[prv[i]][pre[i]]; e.cap-=d; g[i][e.rev].cap+=d; } } //return res; } int main() { cin.tie(0); cout.tie(0); cin>>t; int x,y,z; double q; while(t--) { si(n),si(m); s=0;res=0.0; FOR(i,0,n+1) g[i].clear(); FOR(i,1,n) { si(x),si(y); x-=y; if(x<0) add(i,n+1,abs(x),0); else if(x>0) add(s,i,x,0); } FOR(i,1,m) { si(x),si(y),si(z),sd(q); add(x,y,1,0); if(z>1) add(x,y,z-1,-log(1.0-q)); } slove(s,n+1,inf,n+1); //cout<<flow<<endl; res=1.0-exp(-res); printf("%.2f\n",res); } return 0; }