Codeforces 68 C. Synchrophasotron
問題
n個の頂点からなる有向グラフが与えられる。
それぞれの辺には最小流量、最大流量、およびコストが定められている。
辺(u,v)に流量cのフローを流した場合、
c>0ならコスト(u,v)+c^2のコストがかかり、
c=0ならコストはかからない。
1番の頂点からn番の頂点に流量が整数で、かつ最小のフローを流す。
それが複数ある場合、コストが最大のフローを流す。
流量の最小値およびその時のコストの最大値を出力せよ。
ただしフローが流れない場合は-1 -1を出力せよ。
制約条件
n≦6
最小流量,最大流量≦6
方針
フローっぽい問題であるが、コストが流量の線形になっていないため、多項式時間で求めるのは難しそうである。
ここでは制約が小さいので、全探索する。
途中で流量保存則などが満たされていない場合、その時点で枝刈りしてやることで、最大ケースに対しても50msくらいで終わる。
ソースコード
int n; int l[6][6],h[6][6],a[6][6]; int flow[6][6],total; int mxcost,cost; void rec(int c,int e){ if(e==n){ int in=0, out=0; rep(i,n)in+=flow[i][c], out+=flow[c][i]; if(c==0&&out==total||c==n-1&&in==total||c!=0&&c!=n-1&&in==out)rec(c+1,c+2); return; } if(c==n){ mxcost=max(mxcost,cost); return; } for(int i=l[c][e];i<=h[c][e];i++){ flow[c][e]+=i; cost+=(i?a[c][e]:0)+i*i; rec(c,e+1); cost-=(i?a[c][e]:0)+i*i; flow[c][e]-=i; } } void run(){ cin>>n; rep(i,n*(n-1)/2){ int s,t,L,H,A; cin>>s>>t>>L>>H>>A; s--; t--; l[s][t]=L; h[s][t]=H; a[s][t]=A; } for(total=0;total<=36;total++){ mxcost=-(int)1e9; memset(flow,0,sizeof(flow)); cost=0; rec(0,1); if(mxcost>=0){ cout<<total<<" "<<mxcost<<endl; return; } } cout<<-1<<" "<<-1<<endl; }