【二分答案】【最大流】bzoj3130 [Sdoi2013]费用流
二分最大的边的cap,记作Lim。
把所有的边的cap设为min(Lim,cap[i])。
Bob一定会把单位费用加到最大边上。
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> using namespace std; #define EPS 0.000001 #define N 101 #define INF 2147483647.0 #define M 1001 typedef double db; int n,m,K,S,T; int v[M<<1],next[M<<1],first[N],en; db cap[M<<1]; void AddEdge(int U,int V,db Cap) { v[en]=V; cap[en]=Cap; next[en]=first[U]; first[U]=en++; v[en]=U; cap[en]=0; next[en]=first[V]; first[V]=en++; } queue<int>q; int d[N],cur[N]; bool bfs() { memset(d,-1,sizeof(int)*(n+1)); d[S]=0; q.push(S); while(!q.empty()) { int U=q.front(); q.pop(); for(int i=first[U];i!=-1;i=next[i]) if(d[v[i]]==-1&&cap[i]>EPS) { d[v[i]]=d[U]+1; q.push(v[i]); } } return d[T]!=-1; } db dfs(int U,db a) { if(U==T||a<=EPS) return a; db Flow=0.0,f; for(int &i=cur[U];i!=-1;i=next[i]) if(d[v[i]]==d[U]+1&&(f=(dfs(v[i],min(a,cap[i]))))>EPS) { cap[i]-=f; cap[i^1]+=f; Flow+=f; a-=f; if(a<=EPS) break; } if(Flow<=EPS) d[U]=-1; return Flow; } db MaxFlow() { db Flow=0.0,tmp; while(bfs()) { memcpy(cur,first,sizeof(int)*(n+1)); while((tmp=dfs(S,INF))>EPS) Flow+=tmp; } return Flow; } int xs[M],ys[M],zs[M]; int ChuShi; bool check(db Lim) { memset(first,-1,sizeof(int)*(n+1)); en=0; for(int i=1;i<=m;++i) AddEdge(xs[i],ys[i],min((db)zs[i],Lim)); db t=MaxFlow(); return fabs(t-(db)ChuShi)<=EPS?1:0; } int main() { // freopen("bzoj3130.in","r",stdin); db r=0.0,l=0.0; scanf("%d%d%d",&n,&m,&K); S=1; T=n; memset(first,-1,sizeof(int)*(n+1)); for(int i=1;i<=m;++i) { scanf("%d%d%d",&xs[i],&ys[i],&zs[i]); AddEdge(xs[i],ys[i],(db)zs[i]); r=max(r,(db)zs[i]); } ChuShi=(int)MaxFlow(); while(r-l>EPS) { db mid=(l+r)/2.0; if(check(mid)) r=mid-EPS; else l=mid+EPS; } printf("%d\n%.4lf\n",ChuShi,l*(db)K); return 0; }
——The Solution By AutSky_JadeK From UESTC
转载请注明出处:http://www.cnblogs.com/autsky-jadek/