1. 程式人生 > >[學習筆記] UVA 1659 Help Little Laura - 最大費用迴圈流 - 學習筆記

[學習筆記] UVA 1659 Help Little Laura - 最大費用迴圈流 - 學習筆記

先邊權取負變為最小費用迴圈流。
然後對於邊<u,v,f,c>,如果c>=0,則還是連<u,v,f,c>。
否則建立源點匯點,連<s,v,f,0>,<v,t,f,0>,<v,u,f,-c>,並且ans+=c。
然後ans+最小費用最大流就是答案。
本質類似帶下界費用流和最大權閉合子圖,先欽定負權邊都跑了,然後退最小費用的流使得流量平衡。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long #define db double #define ull unsigned lint #define pb push_back #define mp make_pair #define fir first #define sec second #define gc getchar() #define debug(x) cerr<<#x<<"="<<x #define sp <<" " #define ln <<endl using namespace std; typedef pair<
int,int> pii; typedef set<int>::iterator sit; inline int inn() { int x,ch;while((ch=gc)<'0'||ch>'9'); x=ch^'0';while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');return x; } const int INF=INT_MAX/2-10,N=110,M=100010;const db eps=1e-10; inline int squ(int x) { return
x*x; } struct edges{ int from,to,pre,resf;db wgt; }e[M];int h[N],etop,inq[N],fr[N],x[N],y[N],frs[N];db d[N];queue<int> q;vector<int> to[N]; inline int add_edge(int u,int v,int f,db c,int x=0) { return e[x=++etop].from=u,e[x].to=v,e[x].pre=h[u],h[u]=x,e[x].wgt=c,e[x].resf=f; } inline int build_edge(int u,int v,int f,db c) { return add_edge(u,v,f,c),add_edge(v,u,0,-c); } inline bool spfa(int s,int t,int n,db &ans) { while(!q.empty()) q.pop(); rep(i,1,n) d[i]=INF,inq[i]=0,fr[i]=0; d[s]=0,q.push(s),inq[s]=1; while(!q.empty()) { int x=q.front();q.pop(),inq[x]=0; for(int i=h[x],y;i;i=e[i].pre) if(e[i].resf&&d[y=e[i].to]>d[x]+e[i].wgt) d[y]=d[x]+e[i].wgt,fr[y]=i,(!inq[y]?q.push(y),inq[y]=1:0); } if(!fr[t]) return false;int minf=INF; for(int i=fr[t];i;i=fr[e[i].from]) minf=min(minf,e[i].resf); for(int i=fr[t];i;i=fr[e[i].from]) e[i].resf-=minf,e[((i-1)^1)+1].resf+=minf; return ans+=d[t]*minf,true; } inline db dinic(int s,int t,int n) { db ans=0.0;while(spfa(s,t,n,ans));return ans; } int main() { // freopen("data.in","r",stdin),freopen("std.out","w",stdout); for(int n,cas=1;(n=inn());cas++) { int X=inn(),Y=inn(); rep(i,1,n) { x[i]=inn(),y[i]=inn(),to[i].clear(); for(int t;(t=inn());to[i].pb(t)); } db ans=0;int s=n+1,t=s+1; memset(h,0,sizeof(int)*(t+1)),etop=0; memset(frs,0,sizeof(int)*(t+1)); rep(i,1,n) Rep(j,to[i]) { int a=i,b=to[i][j]; db d=Y-sqrt(squ(x[a]-x[b])+squ(y[a]-y[b]))*X; if(d>=0) build_edge(a,b,1,d); else frs[b]++,frs[a]--,build_edge(b,a,1,-d),ans+=d; } rep(i,1,n) if(frs[i]>0) build_edge(s,i,frs[i],0); else if(frs[i]<0) build_edge(i,t,-frs[i],0); ans+=dinic(s,t,t),printf("Case %d: %.2lf\n",cas,double(-ans+eps)); } return 0; }