您的位置:首页 > 其它

hdu 3667 (拆边 mcmf)

2013-08-17 09:24 363 查看
注意题目中 边的容量 <= 5.可以把费用权值 a *f ^2化归成 a * f2, 即第一条边费用为 1 * a, 第二条 为 (4 - 1) * a, 第三条为 (9 - 4) * a。。。。。。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

const int maxn = 110;
const int maxm = 25000;
const int inf = 0x3f3f3f3f;
const int ww[5] = {1, 3, 5, 7, 9};

struct MCMF
{
struct Edge
{
int v, c, w, next;
}p[maxm << 1];
int e, head[maxn], dis[maxn], pre[maxn], cnt[maxn], sumFlow, n;
bool vis[maxn];
void init(int nt)
{
e = 0; n = nt;
memset(head, -1, sizeof(head[0]) * (n + 2));
}
void addEdge(int u, int v, int c, int w)
{
p[e].v = v; p[e].c = c; p[e].w = w; p[e].next = head[u]; head[u] = e++;
swap(u, v);
p[e].v = v; p[e].c = 0; p[e].w =-w; p[e].next = head[u]; head[u] = e++;
}
bool spfa(int S, int T)
{
queue <int> q;
for (int i = 0; i <= n; ++i)
vis[i] = cnt[i] = 0, pre[i] = -1, dis[i] = inf;
vis[S] = 1; dis[S] = 0;
q.push(S);
while (!q.empty())
{
int u = q.front(); q.pop();
vis[u] = 0;
for (int i = head[u]; i + 1; i = p[i].next)
{
int v = p[i].v;
if (p[i].c && dis[v] > dis[u] + p[i].w)
{
dis[v] = dis[u] + p[i].w;
pre[v] = i;
if (!vis[v])
{
q.push(v);
vis[v] = 1;
if (++cnt[v] > n) return 0;
}
}
}
}
return dis[T] != inf;
}
int mcmf(int S, int T)
{
sumFlow = 0;
int minFlow = 0, minCost = 0;
while (spfa(S, T))
{
minFlow = inf + 1;
for (int i = pre[T]; i + 1; i = pre[ p[i ^ 1].v ])
minFlow = min(minFlow, p[i].c);
sumFlow += minFlow;
for (int i = pre[T]; i + 1; i = pre[ p[i ^ 1].v ])
p[i].c -= minFlow, p[i ^ 1].c += minFlow;
minCost += dis[T] * minFlow;
}
return minCost;
}
void build(int nt, int mt, int kt)
{
init(nt);
addEdge(0, 1, kt, 0);
int u, v, c, w;
for (int i = 0; i < mt; ++i)
{
scanf("%d%d%d%d", &u, &v, &w, &c);
for (int j = 0; j < c; ++j)
addEdge(u, v, 1, w * ww[j]);
}
}
void solve(int nt, int mt, int kt)
{
build(nt, mt, kt);
int ans = mcmf(0, n);
//    cout <<"sumFlow = "  << sumFlow << " cost = " << ans << endl;
if (sumFlow != kt)
printf("-1\n");
else
printf("%d\n", ans);
}
}my;

int main()
{
int n, m, k;
while (~scanf("%d%d%d", &n, &m, &k))
my.solve(n, m, k);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: