因为这个流量的平方乘以ai为代价,就很烦,一般的费用流,怎么改姿势都处理不了。然后又看题解发现了神奇方法。。。
将每条边的费用变成1ai,3ai,5ai,9ai,且流量为1,这样吧1条边拆成多条边,流量为1就是1ai,流量为2就是走2条边,(1+3)=4ai=2*2ai;'
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxl 210
#define inf 2000000001
using namespace std;
int n,m,k,cnt,ans,S,T,sum;
int a[maxl],dis[maxl],ehead[maxl],cur[maxl],from[maxl];
struct ed{int from,to,w,c,nxt;} e[maxl*maxl*5];
bool in[maxl];
void add(int u,int v,int w,int c)
{
e[++cnt].to=v;e[cnt].from=u;e[cnt].w=w;e[cnt].c=c;e[cnt].nxt=ehead[u];ehead[u]=cnt;
e[++cnt].to=u;e[cnt].from=v;e[cnt].w=0;e[cnt].c=-c;e[cnt].nxt=ehead[v];ehead[v]=cnt;
}
void prework()
{
int u,v,w,c,last;cnt=0;
memset(ehead,0,sizeof(ehead));
for(int i=1;i<=m;i++)
{
scanf("%d%d%d%d",&u,&v,&c,&w);
last=0;
for(int j=1;j<=w;j++)
{
add(u,v,1,c*(j*j-last));
last=j*j;
}
}
add(0,1,k,0);
add(n,n+1,k,0);
S=0;T=n+1;
}
bool spfa()
{
int head=0,tail=1,u,v;
for(int i=S;i<=T;i++)
dis[i]=inf,in[i]=false;
a[1]=S;dis[S]=0;in[S]=true;
while(head!=tail)
{
head=(head+1)%maxl;u=a[head];in[u]=false;
for(int i=ehead[u];i;i=e[i].nxt)
{
v=e[i].to;
if(e[i].w>0 && dis[v]>dis[u]+e[i].c)
{
dis[v]=dis[u]+e[i].c;
from[v]=i;
if(!in[v])
{
tail=(tail+1)%maxl;
a[tail]=v;in[v]=true;
}
}
}
}
if(dis[T]==inf)
return false;
else
return true;
}
void mcf()
{
int t=inf,i=from[T],j;
while(i)
{
t=min(e[i].w,t);
i=from[e[i].from];
}
i=from[T];
while(i)
{
if(i&1) j=i+1;
else j=i-1;
ans+=t*e[i].c;
e[i].w-=t,e[j].w+=t;
i=from[e[i].from];
}
sum+=t;
}
void mainwork()
{
ans=0;sum=0;
while(spfa())
mcf();
}
void print()
{
if(sum<k)
printf("-1\n");
else
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d%d%d",&n,&m,&k))
{
prework();
mainwork();
print();
}
return 0;
}