第一道拆边题 用Bellman-Ford以967ms险过...
先说一下大体的题意:输入N M K 分别指城市的个数 M条边 现在需要把K个单位的物品从城市1运往城市N
接下来的M行 每一行输入四个数 ui, vi, ai, Ci
代表从城市u到城市v有一条单向路 容量为c 如果在这条路上运送x个单位的物品 需要花费a*x*x的费用
求最小费用 若不能成功将这K个物品运输到城市N 输出-1
思路:拆边 M条边 对于每一条边 每条边都可以分成c条边
这c条边 容量都为1 花费为 1a 3a 5a 7a 最多到9a(因为c最大是5)
如果流量为1 就会走第一条边 花费a*1*1的费用
如果流量为2 就会走第一条和第二条边 花费为1a+3a == a*2*2
同理依次类推
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<string>
#include<stack>
#include<queue>
#include<cmath>
#include<stack>
#include<list>
#include<map>
#include<set>
typedef long long ll;
using namespace std;
#define MV 11000 //max number of node
#define INF 0x3f3f3f3f
struct edge
{
int t, cap, cost, rev;
edge(int to = 0, int c = 0, int ct = 0, int r = 0): t(to), cap(c), cost(ct), rev(r) {};
};
vector <edge> G[MV];
int dis[MV];//the distance from source
int prevv[MV], preve[MV];//the previous node and the previous edge
int min_cost_flow(int v,int s, int t, int f)
{
int ans = 0, i, j;
while(f > 0)
{
fill(dis, dis + v, INF);
dis[s] = 0;
bool update = true;
while(update)
{//bellman
update = false;
for(i = 0; i < v; ++i)
{
int size1 = G[i].size();
if(dis[i] == INF)
continue;
for(j = 0; j < size1; ++j)
{
edge &es = G[i][j];
if(es.cap > 0 && dis[es.t] > dis[i] + es.cost)
{
dis[es.t] = dis[i] + es.cost;
prevv[es.t] = i;
preve[es.t] = j;
update = true;
}
}
}
}
if(dis[t] == INF)
return -1;
int d = f;
for(i = t; i != s; i = prevv[i])
d = min(d, G[prevv[i]][preve[i]].cap);
ans += d * dis[t];
f -= d;
for(i = t; i != s; i = prevv[i])
{
edge &es = G[prevv[i]][preve[i]];
es.cap -= d;
G[es.t][es.rev].cap += d;
}
}
return ans;
}
void addedge(int s1,int t1,int cap,int cost)
{
G[s1].push_back(edge(t1, cap, cost, G[t1].size()));
G[t1].push_back(edge(s1, 0, -cost, G[s1].size() - 1));
}
int main()
{
int N,M,K;
int i;
while(scanf("%d%d%d",&N,&M,&K)==3)
{
for(i=0;i<MV;i++)G[i].clear();
int x,y,a,c;
while(M--)
{
scanf("%d%d%d%d",&x,&y,&a,&c);
for(i=1;i<=c;i++)
{
addedge(x, y, 1, (2*i-1)*a);
}
}
addedge(0, 1, K, 0);
addedge(N, N+1, K, 0);
int tt=min_cost_flow( N+2, 0, N+1, K);
printf("%d\n",tt);
}
return 0;
}