洛咕 P2494 [SDOI2011]保密
阿新 • • 發佈:2018-11-17
出題人沒素質啊,強行拼題還把題面寫得又臭又長。
簡單題面就是有一張圖,每條邊有兩個權值\(t,s\),有無限支軍隊,一支軍隊可以打一個點,代價是從n到這個點的路徑的\(\frac{\sum t}{\sum s}\)。
有m條限制,每條限制就是a,b兩個點至少選一個,求最小代價。
首先第一部分也就是要求每個點的代價,顯然分數規劃,隨便做做就沒了。
第二部分就是裸的最小割,隨便做做就沒了。
#include<bits/stdc++.h> #define il inline #define vd void typedef long long ll; il int gi(){ int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')f=-1; ch=getchar(); } while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } #define maxn 710 int n,m; struct edge{int d,t,s;}; std::vector<edge>G[maxn]; double W[maxn],dist[maxn];int s[maxn],_s[maxn]; il vd SPFA(double Mid){ static bool inq[maxn]; static int que[maxn],hd,tl; for(int i=1;i<=n;++i)dist[i]=1e9; hd=tl=0;que[tl++]=n;dist[n]=0; while(hd^tl){ int x=que[hd]; for(int i=0;i<G[x].size();++i) if(dist[G[x][i].d]>dist[x]+G[x][i].t-Mid*G[x][i].s){ dist[G[x][i].d]=dist[x]+G[x][i].t-Mid*G[x][i].s; if(!inq[G[x][i].d])inq[G[x][i].d]=1,que[tl++]=G[x][i].d,tl%=maxn; } inq[x]=0;++hd;hd%=maxn; } } il vd solve(int l,int r,double L,double R){ if(R-L<1e-3){ L=(L+R)*0.5; for(int i=l;i<=r;++i)W[s[i]]=L; return; } if(l>r)return; double Mid=(L+R)*0.5; SPFA(Mid); int _l=l-1,_r=r+1; for(int i=l;i<=r;++i) if(dist[s[i]]<0)_s[++_l]=s[i]; else _s[--_r]=s[i]; memcpy(s+l,_s+l,4*(r-l+1)); solve(l,_l,L,Mid); solve(_r,r,Mid,R); } #define maxm 100000 int fir[maxn],head[maxn],dep[maxn],dis[maxm],nxt[maxm],id=1,S=maxn-1,T=maxn-2;double w[maxm]; il vd link(int a,int b,double c){ nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c; nxt[++id]=fir[b],fir[b]=id,dis[id]=a,w[id]=0; } il bool BFS(){ static int que[maxn],hd,tl; hd=tl=0;que[tl++]=S; memset(dep,0,sizeof dep);dep[S]=1; while(hd^tl){ int x=que[hd++]; for(int i=fir[x];i;i=nxt[i]) if(w[i]>1e-5&&!dep[dis[i]]) dep[dis[i]]=dep[x]+1,que[tl++]=dis[i]; } return dep[T]; } il double Dinic(int x,double maxflow){ if(x==T)return maxflow; double ret=0; for(int i=fir[x];i;i=nxt[i]) if(w[i]>1e-5&&dep[dis[i]]==dep[x]+1){ double d=Dinic(dis[i],std::min(w[i],maxflow-ret)); w[i]-=d,w[i^1]+=d,ret+=d; if(maxflow-ret<1e-6)break; } return ret; } int main(){ #ifndef ONLINE_JUDGE freopen("2494.in","r",stdin); freopen("2494.out","w",stdout); #endif n=gi(),m=gi(); int a,b,_t,_s; while(m--)a=gi(),b=gi(),_t=gi(),_s=gi(),G[a].push_back((edge){b,_t,_s}); for(int i=1;i<n;++i)s[i]=i; solve(1,n-1,0,7777); for(int i=1;i<=n;++i)if(W[i]>7776)W[i]=1e9; int m1=gi(),n1=gi(); for(int i=1;i<=n1;i+=2)link(S,i,W[i]); for(int i=2;i<=n1;i+=2)link(i,T,W[i]); while(m1--)a=gi(),b=gi(),link(a,b,1e9); double ans=0;while(BFS())memcpy(head,fir,sizeof fir),ans+=Dinic(S,1e9); if(ans>9e8)puts("-1"); else printf("%.1lf\n",ans); return 0; }