hdu 3452 Bonsai【最大流最小割-------Dinic】

时间:2021-06-30 04:29:10

Bonsai

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 995    Accepted Submission(s): 499


Problem Description After being assaulted in the parking lot by Mr. Miyagi following the "All Valley Karate Tournament", John Kreese has come to you for assistance. Help John in his quest for justice by chopping off all the leaves from Mr. Miyagi's bonsai tree!
You are given an undirected tree (i.e., a connected graph with no cycles), where each edge (i.e., branch) has a nonnegative weight (i.e., thickness). One vertex of the tree has been designated the root of the tree.The remaining vertices of the tree each have unique paths to the root; non-root vertices which are not the successors of any other vertex on a path to the root are known as leaves.Determine the minimum weight set of edges that must be removed so that none of the leaves in the original tree are connected by some path to the root.
 
Input The input file will contain multiple test cases. Each test case will begin with a line containing a pair of integers n (where 1 <= n <= 1000) and r (where r ∈ {1,……, n}) indicating the number of vertices in the tree and the index of the root vertex, respectively. The next n-1 lines each contain three integers ui vi wi (where ui, vi ∈ {1,……, n} and 0 <= wi <= 1000) indicating that vertex ui is connected to vertex vi by an undirected edge with weight wi. The input file will not contain duplicate edges. The end-of-file is denoted by a single line containing "0 0".  
Output For each input test case, print a single integer indicating the minimum total weight of edges that must be deleted in order to ensure that there exists no path from one of the original leaves to the root.  
Sample Input
15 15
1 2 1
2 3 2
2 5 3
5 6 7
4 6 5
6 7 4
5 15 6
15 10 11
10 13 5
13 14 4
12 13 3
9 10 8
8 9 2
9 11 3
0 0
 
Sample Output
16
 
Source 2009 Stanford Local ACM Programming Contest

题目大意:

给你一个包含N个点的一个图,其中一个点r作为根,其走向其他节点经过的边对应需要一定的花费.

现在需要去掉一些边,使得从r走不到各个叶子节点,求最小花费。


思路:


1、断开从某点走向某些点的通路,求一个最小花费。很明显的求最小割的问题。


2、那么考虑建图:

①建立源点S,连入节点R,容量设定为INF.

②建立汇点T,将各个叶子节点(源点也有可能度为1,所以这里需要判断)连入汇点T,容量同样设定为INF.

③其他点之间的网络正常建立即可。


3、建好图之后直接跑最大流即可、最大流==最小。


Ac代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
struct node
{
int from;
int to;
int w;
int next;
}e[151515];
int degree[15150];
int cont;
int n,r,ss,tt;
int divv[15150];
int cur[15150];
int head[15150];
void add(int from,int to,int w)
{
e[cont].w=w;
e[cont].to=to;
e[cont].next=head[from];
head[from]=cont++;
}
int makedivv()
{
queue<int >s;
s.push(ss);
memset(divv,0,sizeof(divv));
divv[ss]=1;
while(!s.empty())
{
int u=s.front();
if(u==tt)return 1;
s.pop();
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if(w&&divv[v]==0)
{
divv[v]=divv[u]+1;
s.push(v);
}
}
}
return 0;
}
int Dfs(int u,int maxflow,int tt)
{
if(u==tt)return maxflow;
int ret=0;
for(int &i=cur[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
if(w&&divv[v]==divv[u]+1)
{
int f=Dfs(v,min(maxflow-ret,w),tt);
e[i].w-=f;
e[i^1].w+=f;
ret+=f;
if(ret==maxflow)return ret;
}
}
return ret;
}
void Dinic()
{
int ans=0;
while(makedivv()==1)
{
memcpy(cur,head,sizeof(head));
ans+=Dfs(ss,0x3f3f3f3f,tt);
}
printf("%d\n",ans);
}
int main()
{
while(~scanf("%d%d",&n,&r))
{
if(n==0&&r==0)break;
ss=n+1;
tt=n+2;
cont=0;
memset(degree,0,sizeof(degree));
memset(head,-1,sizeof(head));
for(int i=0;i<n-1;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
add(x,y,w);
add(y,x,0);
add(y,x,w);
add(x,y,0);
degree[x]++;
degree[y]++;
}
add(ss,r,0x3f3f3f3f);
add(r,ss,0);
for(int i=1;i<=n;i++)
{
if(degree[i]==1&&i!=r)
{
add(i,tt,0x3f3f3f3f);
add(tt,i,0);
}
}
Dinic();
}
return 0;
}