您的位置:首页 > 其它

bzoj 1937 最小生成树【费用流】

2016-06-30 14:28 429 查看
题目大意:给定一张无向图和一颗生成树,求使这棵树变成最小生成树的最小代价

我们知道最优情况下如果要改变,树上边只会减小,非树边只会增大。对于每条非树边 j 两端点间的树边 i,就有 wj+dj>=wi−di,就是 di+dj>=wi−wj。

那么建图就是:

· S -> i (1,0)

· i -> j (1,wi−wj)

· j -> T (1,0)

然后跑最大费用流就好啦QAQ

#include<iostream>
#include<cstring>
#include<cstdio>
#define N 805
#define M 100000
#define INF 1000000000
using namespace std;

int n,m,siz = 1,S,T;
int a[55][55],b[55][55],id[55][55],fa[55],x
,y
;
int first
,next[M],to[M],flow[M],cost[M];
int d
,p[M * 10],pre
;
bool v
;

void inser(int x,int y,int w,int c)
{
next[++ siz] = first[x];
first[x] = siz;
to[siz] = y;
flow[siz] = w;
cost[siz] = c;
}

void add_edge(int x,int y,int w,int c)
{
inser(x,y,w,c),inser(y,x,0,-c);
}

bool spfa()
{
int head = 0,tail = 1;
memset(d,192,sizeof(d));
memset(pre,0,sizeof(pre));
d[p[1] = S] = 0;
while (head ^ tail)
{
int x = p[++ head];
v[x] = false;
for (int i = first[x];i;i = next[i])
if (flow[i] && d[to[i]] < d[x] + cost[i])
{
d[to[i]] = d[x] + cost[i];
pre[to[i]] = i;
if (!v[to[i]]) v[p[++ tail] = to[i]] = true;
}
}
return d[T] ^ d[0];
}

int mcmf()
{
int ret = 0;
while (spfa() && d[T] > 0)
{
int w = INF;
for (int i = pre[T];i;i = pre[to[i ^ 1]])
w = min(w,flow[i]);
for (int i = pre[T];i;i = pre[to[i ^ 1]])
flow[i] -= w,flow[i ^ 1] += w;
ret += d[T] * w;
}
return ret;
}

void dfs(int x)
{
for (int y = 1;y <= n;y ++)
if (b[x][y] && y != fa[x])
fa[y] = x,dfs(y);
}

int main()
{
scanf("%d%d",&n,&m);
for (int i = 1;i <= m;i ++)
{
scanf("%d%d",&x[i],&y[i]);scanf("%d",&a[x[i]][y[i]]);
a[y[i]][x[i]] = a[x[i]][y[i]];
id[x[i]][y[i]] = id[y[i]][x[i]] = i;
}
for (int u,v,i = 1;i < n;i ++)
{
scanf("%d%d",&u,&v);
b[u][v] = b[v][u] = a[u][v];
a[u][v] = a[v][u] = 0;
}
for (int i = 1;i <= m;i ++) if (a[x[i]][y[i]])
{
int u = x[i],v = y[i],w = a[u][v];
fa[v] = 0,dfs(v);
for (int z = u;z ^ v;z = fa[z])
if (b[z][fa[z]] > w) add_edge(id[z][fa[z]],i,1,b[z][fa[z]] - w);
}
S = m+1,T = S+1;
for (int i = 1;i <= m;i ++)
b[x[i]][y[i]] ? add_edge(S,i,1,0) : add_edge(i,T,1,0);
cout << mcmf() << endl;

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: