您的位置:首页 > 其它

UVa1486 Transportation(最小费用最大流)

2016-08-01 15:49 567 查看
题目大概说有n个城市,m条有向边连着它们,每条边都有两个属性一个是ai一个是ci,ai表示运送x单位货物时花费ai*x*x的价钱,ci表示边最多能运送的货物数量(<=5)。问从城市1运送k单位货物到城市n的最少代价。

这种单位费用不固定的费用流很经典的建图方式就是拆边,这题把边拆成ci条,每条单位费用分别为ai*1、ai*3、ai*5、ai*7。。这样如果只有一单位流量通过这条边那么费用就是ai,如果两单位流量那么费用就是ai*1+ai*3=ai*2*2 。。。

那么这题就迎刃而解了。

#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define MAXN 111
#define MAXM 55555
#define INF (1<<30)

struct Edge{
int v,cap,cost,next;
}edge[MAXM];
int vs,vt,NV,NE,head[MAXN];
void addEdge(int u,int v,int cap,int cost){
edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].v=u; edge[NE].cap=0; edge[NE].cost=-cost;
edge[NE].next=head[v]; head[v]=NE++;
}

int d[MAXN],pre[MAXN];
bool inque[MAXN];
bool SPFA(){
for(int i=0; i<NV; ++i){
d[i]=INF; inque[i]=0;
}
d[vs]=0; inque[vs]=1;
queue<int> que;
que.push(vs);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-1; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap && d[v]>d[u]+edge[i].cost){
d[v]=d[u]+edge[i].cost;
pre[v]=i;
if(!inque[v]){
inque[v]=1;
que.push(v);
}
}
}
inque[u]=0;
}
return d[vt]!=INF;
}
int mxflow;
int MCMF(){
mxflow=0;
int res=0;
while(SPFA()){
int flow=INF,cost=0;
for(int u=vt; u!=vs; u=edge[pre[u]^1].v){
flow=min(flow,edge[pre[u]].cap);
}
mxflow+=flow;
for(int u=vt; u!=vs; u=edge[pre[u]^1].v){
edge[pre[u]].cap-=flow;
edge[pre[u]^1].cap+=flow;
cost+=edge[pre[u]].cost;
}
res+=cost*flow;
}
return res;
}

int main(){
int n,m,k;
while(~scanf("%d%d%d",&n,&m,&k)){
vs=0; vt=n; NV=vt+1; NE=0;
memset(head,-1,sizeof(head));
addEdge(vs,1,k,0);

int u,v,a,c;
while(m--){
scanf("%d%d%d%d",&u,&v,&a,&c);
for(int i=1; i<=c; ++i){
addEdge(u,v,1,a*(2*i-1));
}
}
int res=MCMF();
if(mxflow!=k) puts("-1");
else printf("%d\n",res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: