您的位置:首页 > 大数据 > 人工智能

HDU 3452 Bonsai

2013-10-31 09:56 134 查看
题意:给出一颗树和树根,每条树边都有边权,要你砍断一些边,使得所有的叶子节点都与根节点分离,且要求砍断的边权之和最小。

以树根root为源点S,添加一个汇点T,对所有的非跟叶子节点i,加边(i,T,inf),求最小割即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define INF 1<<30
#define maxn 1010
#define maxm 10000
using namespace std;

int u[maxm],v[maxm],next[maxm],w[maxm];
int first[maxn],d[maxn],work[maxn],q[maxn],vis[maxn];
int e,S,T;
int degree[maxn];

void init(){
e = 0;
memset(first,-1,sizeof(first));
}

void add_edge(int a,int b,int c){
u[e] = a;v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++;
u[e] = b;v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++;
}

int bfs(){
int rear = 0;
memset(d,-1,sizeof(d));
d[S] = 0;q[rear++] = S;
for(int i = 0;i < rear;i++){
for(int j = first[q[i]];j != -1;j = next[j])
if(w[j] && d[v[j]] == -1){
d[v[j]] = d[q[i]] + 1;
q[rear++] = v[j];
if(v[j] == T)   return 1;
}
}
return 0;
}

int dfs(int cur,int a){
if(cur == T)    return a;
for(int &i = work[cur];i != -1;i = next[i]){
if(w[i] && d[v[i]] == d[cur] + 1)
if(int t = dfs(v[i],min(a,w[i]))){
w[i] -= t;w[i^1] += t;
return t;
}
}
return 0;
}

int dinic(){
int ans = 0;
while(bfs()){
memcpy(work,first,sizeof(first));
while(int t = dfs(S,INF))   ans += t;
}
return ans;
}

int main()
{
int n,root;
while(scanf("%d%d",&n,&root) == 2){
if(!n && !root) break;
memset(degree,0,sizeof(degree));
S = root,T = n+1;
init();
for(int i = 0;i < n-1;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
add_edge(a,b,c);
add_edge(b,a,c);
degree[a]++;degree[b]++;
}
for(int i = 1;i <= n;i++){
if(degree[i] == 1 && i != root)
add_edge(i,T,INF);
}
printf("%d\n",dinic());
}
return 0;
}


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