题目意思是给定一个图,求从起点送货物到终点的最小花费。
典型的最小费用流题目。不过由于花费的计算方法是a*x*x,因此必须拆边,使得最小费用流模板可用,即变成a*x的形式。由于是平方式,有1=1,4=1+3,9=1+3+5.。。。因此拆边的方法为做一个循环,第i次取这条路时费用为(2*i-1)*a (i<=5),每条边的容量为1。
以下是代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<utility>
#include<string>
#include<set>
#include<vector>
#include<stack>
#include<algorithm>
#include<queue>
#include<cstdlib>
#include<map>
#include<cmath>
using namespace std;
#define FOR(i,a,b) for(int i(a);i<(b);i++)
#define REP(i,n) FOR(i,0,n)
#define CL(a,b) memset(a,b,sizeof(a))
const int M=5010;
const int N=120;
//const __int64 inf=0x7fffffffffffffff;
const int inf=1<<29;
//const double inf=1e250;
const double eps=1e-8;
const double pi=acos(-1.0);
const double sq2=sqrt(2.0);
struct node
{
int u,v,flow,cap,cost;
int next;
}edge[4*M];
int head[N],num;
int low[N],p[N],dist[N];
bool vis[N];
int ans,anscost;
int n,m,k;
int s,t;
void init()
{
num=0;
for(int i=0;i<=n+3;i++)
{
head[i]=-1;
}
}
void addege(int u,int v,int cost,int cap)
{
edge[num].u=u;
edge[num].v=v;
edge[num].cost=cost;
edge[num].cap=cap;
edge[num].flow=0;
edge[num].next=head[u];
head[u]=num++;
edge[num].u=v;
edge[num].v=u;
edge[num].cost=-cost;
edge[num].cap=0;
edge[num].flow=0;
edge[num].next=head[v];
head[v]=num++;
}
bool spfa()
{
queue<int> q;
memset(vis,false,sizeof(vis));
memset(p,-1,sizeof(p));
fill(&dist[0],&dist[N],inf);
vis[s]=1,low[s]=inf,dist[s]=0;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=false;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v,cost=edge[i].cost,cap=edge[i].cap,flow=edge[i].flow;
if(flow<cap && dist[u]+cost<dist[v])
{
dist[v]=dist[u]+cost;
p[v]=i;
low[v]=min(low[u],cap-flow);
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
return dist[t]!=inf;
}
void costflow()
{
ans=anscost=0;
while(spfa())
{
int x=p[t];
ans+=low[t];
anscost+=low[t]*dist[t];
while(x!=-1)
{
edge[x].flow+=low[t];
edge[x^1].flow-=low[t];
edge[x^1].cost=-edge[x].cost;
x=p[edge[x].u];
}
}
}
int main()
{
while(scanf("%d%d%d",&n,&m,&k)==3)
{
init();
for(int i=0;i<m;i++)
{
int u,v,a,c;
scanf("%d%d%d%d",&u,&v,&a,&c);
for(int i=0;i<c;i++)
addege(u,v,(2*i+1)*a,1);
}
addege(0,1,0,k);
s=0;t=n;
costflow();
if(ans<k)
puts("-1");
else
printf("%d\n",anscost);
}
return 0;
}