2020.7.29【算协集训】树的直径—HPU算法协会暑假训练

树的直径

  • A - Labyrinth (POJ-1383)
  • B - Roads in the North (POJ-2631)
  • C - Cow Marathon (POJ-1985)
  • D - Computer (HDU-2196)
  • E - Farthest Nodes in a Tree (LightOJ-1094)
  • F - Caterpillar (POJ-3310)

网页链接:传送门
密码:hpuacmacm

A - Labyrinth (POJ-1383)

The northern part of the Pyramid contains a very large and complicated labyrinth. The labyrinth is divided into square blocks, each of them either filled by rock, or free. There is also a little hook on the floor in the center of every free block. The ACM have found that two of the hooks must be connected by a rope that runs through the hooks in every block on the path between the connected ones. When the rope is fastened, a secret door opens. The problem is that we do not know which hooks to connect. That means also that the neccessary length of the rope is unknown. Your task is to determine the maximum length of the rope we could need for a given labyrinth.
Input
The input consists of T test cases. The number of them (T) is given on the first line of the input file. Each test case begins with a line containing two integers C and R (3 <= C,R <= 1000) indicating the number of columns and rows. Then exactly R lines follow, each containing C characters. These characters specify the labyrinth. Each of them is either a hash mark (#) or a period (.). Hash marks represent rocks, periods are free blocks. It is possible to walk between neighbouring blocks only, where neighbouring blocks are blocks sharing a common side. We cannot walk diagonally and we cannot step out of the labyrinth.
The labyrinth is designed in such a way that there is exactly one path between any two free blocks. Consequently, if we find the proper hooks to connect, it is easy to find the right path connecting them.
Output
Your program must print exactly one line of output for each test case. The line must contain the sentence “Maximum rope length is X.” where Xis the length of the longest path between any two free blocks, measured in blocks.

Sample Input

2
3 3
###
#.#
###
7 6
#######
#.#.###
#.#.###
#.#.#.#
#.....#
#######

Sample Output

Maximum rope length is 0.
Maximum rope length is 8.
#include
#include
using namespace std;
typedef long long ll;
const ll maxn=1010;

int T,C,R,firx,firy,endx,endy,mal;
bool bj[maxn][maxn];
char g[maxn][maxn];
int dx[4]={0,0,-1,1};
int dy[4]={1,-1,0,0};

void dfs(int x,int y,int depth)
{
	bj[x][y]=true;
	if(mal<depth)
	{
		endx=x;
		endy=y;
		mal=depth;
	}
	for(int i=0;i<4;i++)
	{
		int xx=x+dx[i],yy=y+dy[i];
		if(xx>=0&&xx<R && yy>=0&&yy<C && !bj[xx][yy] && g[xx][yy]=='.')
		{
			bj[xx][yy]=true;
			dfs(xx,yy,depth+1);
		}
	}
}

int main()
{
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&C,&R);
		memset(bj,false,sizeof(bj));
		mal=0;
		for(int i=0;i<R;i++)	scanf("%s",&g[i]);
		for(int i=0;i<R;i++)
		{
			for(int j=0;j<C;j++)
			{
				if(g[i][j]=='.')
				{
					firx=i;
					firy=j;
					break;
				}
			}
		}
		dfs(firx,firy,0);
		memset(bj,false,sizeof(bj));
		dfs(endx,endy,0);
		printf("Maximum rope length is %d.\n",mal);
	}
	return 0;
}

B - Roads in the North (POJ-2631)

Building and maintaining roads among communities in the far North is an expensive business. With this in mind, the roads are build such that there is only one route from a village to a village that does not pass through some other village twice.
Given is an area in the far North comprising a number of villages and roads among them such that any village can be reached by road from any other village. Your job is to find the road distance between the two most remote villages in the area.
The area has up to 10,000 villages connected by road segments. The villages are numbered from 1.
Input
Input to the problem is a sequence of lines, each containing three positive integers: the number of a village, the number of a different village, and the length of the road segment connecting the villages in kilometers. All road segments are two-way.
Output
You are to output a single integer: the road distance between the two most remote villages in the area.

Sample Input Sample Output
5 1 6
1 4 5
6 3 9
2 6 8
6 1 7
22
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll maxn=1e6+10;

int T,u,v,w,ne,maxm,maxv;
int head[maxn];
bool bj[maxn];
char c;

struct edge
{
	int to,next,w;
}edges[maxn];

void add(int u,int v,int w)
{
	edges[ne].to=v;
	edges[ne].next=head[u];
	edges[ne].w=w;
	head[u]=ne++;
}

void dfs(int u,int depth)
{
	bj[u]=true;
	if(maxm<depth)
	{
		maxv=u;
		maxm=depth;
	}
	for(int e=head[u];e!=-1;e=edges[e].next)
	{
		int v=edges[e].to;
		if(!bj[v])
		{
			int w=edges[e].w;
			dfs(v,depth+w);
			bj[v]=false;
		}
	}
}

int main()
{
	ne=maxm=0;
	memset(head,-1,sizeof(head));
	memset(bj,false,sizeof(bj));
	while(~scanf("%d%d%d",&u,&v,&w))
	{
		add(u,v,w);
		add(v,u,w);
	}
	dfs(1,0);
	maxm=0;
	memset(bj,false,sizeof(bj));
	dfs(maxv,0);
	printf("%d\n",maxm);
	return 0;
}

C - Cow Marathon (POJ-1985)

After hearing about the epidemic of obesity in the USA, Farmer John wants his cows to get more exercise, so he has committed to create a bovine marathon for his cows to run. The marathon route will include a pair of farms and a path comprised of a sequence of roads between them. Since FJ wants the cows to get as much exercise as possible he wants to find the two farms on his map that are the farthest apart from each other (distance being measured in terms of total length of road on the path between the two farms). Help him determine the distances between this farthest pair of farms.
Input
* Lines 1…: Same input format as “Navigation Nightmare”.
Output
* Line 1: An integer giving the distance between the farthest pair of farms.

Sample Input Sample Output
7 6
1 6 13 E
6 3 9 E
3 5 7 S
4 1 3 N
2 4 20 W
4 7 2 S
52
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll maxn=1e6+10;

int N,M,u,v,w,ne,maxm,maxv;
int head[maxn];
bool bj[maxn];
char c;

struct edge
{
	int to,next,w;
}edges[maxn];

void add(int u,int v,int w)
{
	edges[ne].to=v;
	edges[ne].next=head[u];
	edges[ne].w=w;
	head[u]=ne++;
}

void dfs(int u,int depth)
{
	bj[u]=true;
	if(maxm<depth)
	{
		maxv=u;
		maxm=depth;
	}
	for(int e=head[u];e!=-1;e=edges[e].next)
	{
		int v=edges[e].to;
		if(!bj[v])
		{
			int w=edges[e].w;
			dfs(v,depth+w);
			bj[v]=false;
		}
	}
}

int main()
{
	scanf("%d%d",&N,&M);
	ne=maxm=0;
	memset(head,-1,sizeof(head));
	memset(bj,false,sizeof(bj));
	while(M--)
	{
		scanf("%d%d%d%c",&u,&v,&w,&c);
		getchar();
		add(u,v,w);
		add(v,u,w);
	}
	dfs(1,0);
	maxm=0;
	memset(bj,false,sizeof(bj));
	dfs(maxv,0);
	printf("%d\n",maxm);
	return 0;
}

D - Computer (HDU-2196)

A school bought the first computer some time ago(so this computer’s id is 1). During the recent years the school bought N-1 new computers. Each new computer was connected to one of settled earlier. Managers of school are anxious about slow functioning of the net and want to know the maximum distance Si for which i-th computer needs to send signal (i.e. length of cable to the most distant computer). You need to provide this information.
2020.7.29【算协集训】树的直径—HPU算法协会暑假训练_第1张图片
Hint: the example input is corresponding to this graph. And from the graph, you can see that the computer 4 is farthest one from 1, so S1 = 3. Computer 4 and 5 are the farthest ones from 2, so S2 = 2. Computer 5 is the farthest one from 3, so S3 = 3. we also get S4 = 4, S5 = 4.
Input
Input file contains multiple test cases.In each case there is natural number N (N<=10000) in the first line, followed by (N-1) lines with descriptions of computers. i-th line contains two natural numbers - number of computer, to which i-th computer is connected and length of cable used for connection. Total length of cable does not exceed 10^9. Numbers in lines of input are separated by a space.
Output
For each case output N lines. i-th line must contain number Si for i-th computer (1<=i<=N).

Sample Input Sample Output
5
1 1
2 1
3 1
1 1
3
2
3
4
4
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll maxn=1e6+10;

int N,v,w,maxm,maxv;
int dis[maxn];
vector<pair<int,int>> G[maxn];
bool bj[maxn];

void dfs(int u,int t)
{
	bj[u]=true;
	if(maxm<t)
	{
		maxv=u;
		maxm=t;
	}
	for(auto it:G[u])
	{
		int a=it.first;
		int b=it.second;
		if(!bj[a])
		{
			dis[a]=max(dis[a],t+b);
			dfs(a,t+b);
		}
	}
}

int main()
{
	while(~scanf("%d",&N))
	{
		maxm=maxv=0;
		memset(dis,0,sizeof(dis));
		memset(bj,false,sizeof(bj));
		for(int i=0;i<=N;i++)	G[i].clear();
		for(int i=2;i<=N;i++)
		{
			scanf("%d%d",&v,&w);
			G[i].push_back({v,w});
			G[v].push_back({i,w});
		}
		dfs(1,0);
		memset(bj,false,sizeof(bj));
		dfs(maxv,0);
		memset(bj,false,sizeof(bj));
		dfs(maxv,0);
		for(int i=1;i<=N;i++)
			printf("%d\n",dis[i]);
	}
	return 0;
}

E - Farthest Nodes in a Tree (LightOJ-1094)

Given a tree (a connected graph with no cycles), you have to find the farthest nodes in the tree. The edges of the tree are weighted and undirected. That means you have to find two nodes in the tree whose distance is maximum amongst all nodes.
Input
Input starts with an integer T (≤ 10), denoting the number of test cases.
Each case starts with an integer n (2 ≤ n ≤ 30000) denoting the total number of nodes in the tree. The nodes are numbered from 0 to n-1. Each of the next n-1 lines will contain three integers u v w (0 ≤ u, v < n, u ≠ v, 1 ≤ w ≤ 10000) denoting that node u and v are connected by an edge whose weight is w. You can assume that the input will form a valid tree.
Output
For each case, print the case number and the maximum distance.

Sample Input Sample Output
2
4
0 1 20
1 2 30
2 3 50
5
0 2 20
2 1 10
0 3 29
0 4 50
Case 1: 100
Case 2: 80
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll maxn=1e6+10;

int T,n,u,v,w,ne,maxm,maxv;
int head[maxn];
bool bj[maxn];

struct edge
{
	int to,next,w;
}edges[maxn];

void add(int u,int v,int w)
{
	edges[ne].to=v;
	edges[ne].next=head[u];
	edges[ne].w=w;
	head[u]=ne++;
}

void dfs(int u,int depth)
{
	bj[u]=true;
	if(maxm<depth)
	{
		maxv=u;
		maxm=depth;
	}
	for(int e=head[u];e!=-1;e=edges[e].next)
	{
		int v=edges[e].to;
		if(!bj[v])
		{
			int w=edges[e].w;
			dfs(v,depth+w);
			bj[v]=false;
		}
	}
}

int main()
{
	scanf("%d",&T);
	for(int i=1;i<=T;i++)
	{
		ne=maxm=0;
		memset(head,-1,sizeof(head));
		memset(bj,false,sizeof(bj));
		scanf("%d",&n);
		for(int j=0;j<n-1;j++)
		{
			scanf("%d%d%d",&u,&v,&w);
			getchar();
			add(u,v,w);
			add(v,u,w);
		}
		dfs(1,0);
		maxm=0;
		memset(bj,false,sizeof(bj));
		dfs(maxv,0);
		printf("Case %d: %d\n",i,maxm);
	}
	return 0;
}

F - Caterpillar (POJ-3310)

An undirected graph is called a caterpillar if it is connected, has no cycles, and there is a path in the graph where every node is either on this path or a neighbor of a node on the path. This path is called the spine of the caterpillar and the spine may not be unique. You are simply going to check graphs to see if they are caterpillars.
For example, the left graph below is not a caterpillar, but the right graph is. One possible spine is
shown by dots.2020.7.29【算协集训】树的直径—HPU算法协会暑假训练_第2张图片
Input
There will be multiple test cases. Each test case starts with a line containing n indicating the number of nodes, numbered 1 through n (a value of n = 0 indicates end-of-input). The next line will contain an integer e indicating the number of edges. Starting on the following line will be e pairs n1 n2 indicating an undirected edge between nodes n1 and n1. This information may span multiple lines. You may assume that n ≤ 100 and e ≤ 300. Do not assume that the graphs in the test cases are connected or acyclic.
Output
For each test case generate one line of output. This line should either be
Graph g is a caterpillar.
or
Graph g is not a caterpillar.
as appropriate, where g is the number of the graph, starting at 1.

Sample Input Sample Output
22
21
1 2 2 3 2 4 2 5 2 6 6 7 6 10 10 8 9 10 10 12 11 12 12 13 12 17
18 17 15 17 15 14 16 15 17 20 20 21 20 22 20 19
16
15
1 2 2 3 5 2 4 2 2 6 6 7 6 8 6 9 9 10 10 12 10 11 10 14 10 13 13 16 13 15
0
Graph 1 is not a caterpillar.
Graph 2 is a caterpillar.
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll maxn=1e6+10;

int n,m,u,v,ne,maxm,maxv;	//maxm记录最长的路径长,maxv记录直径的端点 
int head[maxn],dis[maxn],bj[maxn];
bool vis[maxn],check,flag;

struct edge
{
	int to,next;
}edges[maxn];

void add(int u,int v)
{
	edges[ne].to=v;
	edges[ne].next=head[u];
	head[u]=ne++;
}

void dfs1(int u,int fa)	//判断是否是一棵树 
{
	vis[u]=true;
	for(int e=head[u];e!=-1;e=edges[e].next)
	{
		int v=edges[e].to;
		if(v!=fa)	//保证不往回遍历 
		{
			if(vis[v])	//遍历到了标记过的点,证明有环 
			{
				check=true;
				return ;
			}
			dfs1(v,u);
			if(check)	return ;
		}
	}
}

void dfs2(int u,int fa)
{
	vis[u]=true;
	if(dis[u]>maxm)
	{
		maxm=dis[u];
		maxv=u;
	}
	for(int e=head[u];e!=-1;e=edges[e].next)
	{
		int v=edges[e].to;
		if(v!=fa)
		{
			dis[v]=dis[u]+1;
			bj[v]=dis[v];
			dfs2(v,u);
			bj[u]=max(bj[u],bj[v]);	//记录儿子所能传递回来的最大值,就可以标记出树的直径这条链 
		}	//因为这条链上的bj都会等于maxm,而非链上的都会小于maxm 
	}
}

int main()
{
	int cnt=0;
	while(~scanf("%d",&n))
	{
		if(n==0)	break;
		ne=maxm=0;
		check=false;
		memset(head,-1,sizeof(head));
		memset(vis,false,sizeof(vis));
		scanf("%d",&m);
		for(int i=0;i<m;i++)
		{
			scanf("%d%d",&u,&v);
			add(u,v);
			add(v,u);
		}
		if(m>n-1)	check=true;	//边数大于点数-1,就绝对不可能是一棵树 
		if(!check)	dfs1(1,0);
		if(!check)
		{
			for(int i=1;i<=n;i++)
			{
				if(!vis[i])	//存在没有搜到过的点,就不是一棵树 
				{
					check=true;
					break;
				}
			}
			if(!check)
			{
				maxm=0;
				memset(dis,0x3f3f3f3f,sizeof(dis));
				memset(bj,0,sizeof(bj));
				dis[1]=0;
				dfs2(1,0);	//找出树的直径的一个端点 
				dis[maxv]=0;
				dfs2(maxv,0);	//找到完整的链 
				for(int i=1;i<=n;i++)
				{
					flag=false;
					if(bj[i]==maxm)	continue;	//它是链上的点 
					for(int e=head[i];e!=-1;e=edges[e].next)	//如果不是链上的点,也没有和链上的点直接相连,则也是不符合要求的点 
					{
						int v=edges[e].to;
						if(bj[v]==maxm)	//该点有一个出边指向链上的点 
						{
							flag=true;
							break;
						}
					}
					if(!flag)
					{
						check=true;
						break;
					}
				}
			}
		}
		cnt++;
		if(check)	printf("Graph %d is not a caterpillar.\n",cnt);	
		else	printf("Graph %d is a caterpillar.\n",cnt);	
	}
	return 0;
}

你可能感兴趣的:(题解,算法,dfs,acm竞赛)