DFS搜索 --- HihoCoder 1168 Transport

#1168 : Transport

Time Limit: 2000ms
Case Time Limit: 1000ms
Memory Limit: 256MB

Description

Country Z has n cities numbered from 1 to n inclusively. There are n - 1 roads connecting the cities. Every pair of cities is connected by exactly one path, and a path is a sequence of roads. Every city has some goods that need to be transported to city s. Because of the limit of the transportation system, only one unit of goods can be transport via a road in one unit time. The government wants to know the minimum time to finish the transportation.

Input

The first line of input contains a single integer T, specifying the number of test cases.

The first line of each test case contains two integer n and s, indicating the number of the cities and the destination.  Each of next n - 1 lines consists of two integers i and j, indicating that  there is a road between city i and city j. Each of the last n lines contains an integer x, specifying the amount of goods in the cities.

Output

For each test case, output a line containing "Case #X: Y". X is the test case number starting from 1, and Y is the minimum time to finish the transportation.

Limits

1 ≤ T ≤ 20

Small

1 ≤ n ≤ 500

0 ≤ x ≤ 20

Large

1 ≤ n ≤ 100000

0 ≤ x ≤ 100000

Sample Input
2
3 2
1 2
2 3
1 
2 
1
5 1
1 2
2 3
2 4
2 5
5
1
2
2
1
Sample Output
Case #1: 1
Case #2: 6 

        这道题目我觉得相当的有特点,首先是在树上进行的,其次是最优的运输策略还可以很轻易的得出:尽量沿着最短的路径运输,大不了积压在一个节点上,慢慢传就得了。所以说想到这里不应该是动态规划类的题目。那么可能是网络流吗?


        网络流要怎么表示出时间这一个概念呢?加上费用变成最小费用流?依然不科学,因为同一个单位时间内的操作数目本身应该是消耗一个单位时间的,但是用最小费用流就变成了多个。这更是不可取的。




        目前为止没什么思路,那么从小情形开始看。假定x节点是目标节点,它有一些儿子p1,p2,p3。。。。。pN,以及一个父亲F。那么很明显把货物全都运送到x的时间消耗就是这些儿子、父亲中最慢,也就是货物堆积最多的那一个。不仅仅是这个目标节点,每一个节点都一样。


        因此这个题目可以从某种程度上理解成一个一边dfs一边bfs的过程。枚举和当前节点相连的所有点,然后从这些点出发进行dfs。每次dfs返回来的结果就是这个节点的“堆积时间”。最后取一个最大值就得了,整个算法相当简单。上代码:


       

#include<iostream>
#include<string.h>
#include<algorithm>
#include<vector>
#include<stdio.h>
#define N 100005
using namespace std;

vector<int>e[N];
int n,T,v[N],s;
long long int ans = 0;

long long int dfs(int x,int fa)
{
	long long int res = 0;
	for(int i = 0;i<e[x].size();i++)
	{
		if(e[x][i] == fa)continue;
		long long int t = dfs(e[x][i],x);
		ans = max(ans,t);
		res += t;
	}
	res += v[x];
	return res;
}

int main()
{
	cin>>T;
	int cas = 0;
	while(T--)
	{
		ans = 0;
		cin>>n>>s;
		for(int i = 0;i<=n + 1;i++)
		e[i].clear();
		for(int i = 1;i<n;i++)
		{
			int t1,t2;
			cin>>t1>>t2;
			e[t1].push_back(t2);
			e[t2].push_back(t1);
		}
		for(int i = 1;i<=n;i++)
		cin>>v[i];
		dfs(s,-1);
		printf("Case #%d: ", ++cas);
		cout<<ans<<endl;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值