[SDOI2009]晨跑,洛谷P2153,最小費用最大流
阿新 • • 發佈:2018-12-04
正題
給出n個點,m條邊,每條邊有個長度,且只能走一次,讓你規劃一種方案,使得1到n的路徑條數最多而且總路程最短。
很明顯這是一道網路流的題目,我們只要把每一條邊的長度改成費用,流量為1,即可。
沒有用zkw網路流寫法。
#include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<queue> using namespace std; struct edge{ int x,y,next,c,cos; }s[40410]; int n,m; int len=1; int begin,end; int d[410],mmin[410],last[410],first[410]; bool tf[410]; queue<int> f; void ins(int x,int y,int c,int cos){ len++; s[len]=(edge){x,y,first[x],c,cos};first[x]=len; } bool SPFA(int &cost,int&flow){ memset(d,63,sizeof(d)); memset(tf,false,sizeof(tf)); memset(mmin,63,sizeof(mmin)); memset(last,0,sizeof(last)); f.push(begin);d[begin]=0;tf[begin]=true; while(!f.empty()){ int x=f.front();f.pop();tf[x]=false; for(int i=first[x];i!=0;i=s[i].next){ int y=s[i].y; if(d[y]>d[x]+s[i].cos && s[i].c>0){ mmin[y]=min(mmin[x],s[i].c); d[y]=d[x]+s[i].cos; last[y]=i; if(!tf[y]){ tf[y]=true; f.push(y); } } } } if(d[end]==d[end+1]) return false; cost+=d[end]*mmin[end]; flow+=mmin[end]; int now=end; while(now!=begin){ s[last[now]].c-=mmin[end]; s[last[now]^1].c+=mmin[end]; now=s[last[now]].x; } return true; } void MCMF(){ int cost=0,flow=0; while(SPFA(cost,flow)); printf("%d %d\n",flow,cost); } int main(){ scanf("%d %d",&n,&m); begin=0,end=2*n+1; int x,y,c; for(int i=1;i<=m;i++){ scanf("%d %d %d",&x,&y,&c); ins(x,y+n,1,c); ins(y+n,x,0,-c); } for(int i=1;i<=n;i++){ ins(i+n,i,1,0); ins(i,i+n,0,0); } ins(begin,1,1e9,0);ins(n+n,end,1e9,0); MCMF(); }