POJ - 3585 Accumulation Degree 树形DP 二次扫描 与 换根法

Trees are an important component of the natural landscape because of their prevention of erosion and the provision of a specific ather-sheltered ecosystem in and under their foliage. Trees have also been found to play an important role in producing oxygen and reducing carbon dioxide in the atmosphere, as well as moderating ground temperatures. They are also significant elements in landscaping and agriculture, both for their aesthetic appeal and their orchard crops (such as apples). Wood from trees is a common building material.

Trees also play an intimate role in many of the world's mythologies. Many scholars are interested in finding peculiar properties about trees, such as the center of a tree, tree counting, tree coloring. A(x) is one of such properties.

A(x) (accumulation degree of node x) is defined as follows:

  1. Each edge of the tree has an positive capacity.
  2. The nodes with degree of one in the tree are named terminals.
  3. The flow of each edge can't exceed its capacity.
  4. A(x) is the maximal flow that node x can flow to other terminal nodes.

Since it may be hard to understand the definition, an example is showed below:

A(1)=11+5+8=24
Details: 1->2 11
  1->4->3 5
  1->4->5 8(since 1->4 has capacity of 13)
A(2)=5+6=11
Details: 2->1->4->3 5
  2->1->4->5 6
A(3)=5
Details: 3->4->5 5
A(4)=11+5+10=26
Details: 4->1->2 11
  4->3 5
  4->5 10
A(5)=10
Details: 5->4->1->2 10

The accumulation degree of a tree is the maximal accumulation degree among its nodes. Here your task is to find the accumulation degree of the given trees.

Input

The first line of the input is an integer T which indicates the number of test cases. The first line of each test case is a positive integer n. Each of the following n - 1 lines contains three integers xyz separated by spaces, representing there is an edge between node x and node y, and the capacity of the edge is z. Nodes are numbered from 1 to n.
All the elements are nonnegative integers no more than 200000. You may assume that the test data are all tree metrics.

Output

For each test case, output the result on a single line. 
 

Sample Input

1
5
1 2 11
1 4 13
3 4 5
4 5 10

Sample Output

26

题意:有n个点 的一颗    无根树   节点u和节点v之间有一个河道容量为 c(u,v)    树中度为1的节点都是入海口,求一个水的起源点整棵树的水流量最大,求最大值  n<=2e5;

二次扫描与换根法:(来自lyd大佬的  算法竞赛进阶指南)

1:第一次扫描时,任选一个为根节点(通常选1)在树上进行树形DP,在回溯时,从儿子节点到根节点(从底向上)进行状态转移

2:第二次扫描,从刚才选的根节点出发,对树进行DFS,在每次递归前进行  自顶向下的推导   ,计算         换根      后的解

思路:  第一次自底向上dfs 求出    f1[i] 表示以   i  为根的子树的最大流量    f1[i]  +=  min(f1[j],c[i,j])(j是i的子节点)当然有些特殊的点

如果  j度为1  f1[i] += c[i,j]

第二次自顶向下   dfs   求出 f2[i]   表示以   i    为源点 整课树的最大流量      f2[j]=f1[j]+min(     f2[j]-min(f1[j],c[i,j])    ,    c[i,j]])

当然也有特殊的点  当 i 度为1 时    f2[j]=f1[j]+ c[i,j]              画图可以看出状态转移方程  

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<stack>
#include<cstdlib>
#include<deque>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int>P;
const int len=2e5+5;
const ll mod=2147483648;
const double pi=acos(-1.0);
int f1[len],f2[len];
int in[len];
int head[len*2],ver[len*2],val[len*2],nex[len*2];
int n,tot;
void add(int u,int v,int w)
{
	tot++;
	ver[tot]=v;val[tot]=w;
	nex[tot]=head[u];head[u]=tot;
}
void dfs(int u,int p)
{
	for(int i=head[u];i;i=nex[i])
	{
		int v=ver[i],w=val[i];
		if(v!=p)
		{
			dfs(v,u);
			if(in[v]==1)f1[u]+=w;
			else f1[u]+=min(f1[v],w);
		}
	}
}
void DFS(int u,int p)
{
	for(int i=head[u];i;i=nex[i])
	{
		int v=ver[i],w=val[i];
		if(v!=p)
		{
			if(in[u]==1)f2[v]=f1[v]+w;
			else
			f2[v]=f1[v]+min(w,f2[u]-min(w,f1[v]));
			DFS(v,u);
		}
	}
}
int main()
{	
	int t;
	cin>>t;
	while(t--)
	{
		tot=0;
		scanf("%d",&n);
		memset(head,0,sizeof(head));
		memset(f1,0,sizeof(f1));
		memset(f2,0,sizeof(f2));
		memset(in,0,sizeof(in));
		for(int i=2;i<=n;++i)
		{
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			in[u]++;
			in[v]++;
			add(u,v,w);
			add(v,u,w);
		}
		dfs(1,-1);
		f2[1]=f1[1];
		DFS(1,-1);
		int ans=0;
		for(int i=1;i<=n;++i)ans=max(ans,f2[i]);
		printf("%d\n",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/hutwuguangrong/article/details/86666006