藍橋杯PREV-9 大臣的旅費 【深度優先搜索】

時間限制:1.0s   內存限制:256.0MB

問題描述

很久以前,T王國空前繁榮。爲了更好地管理國家,王國修建了大量的快速路,用於連接首都和王國內的各大城市。

爲節省經費,T國的大臣們經過思考,制定了一套優秀的修建方案,使得任何一個大城市都能從首都直接或者通過其他大城市間接到達。同時,如果不重複經過大城市,從首都到達每個大城市的方案都是唯一的。

J是T國重要大臣,他巡查於各大城市之間,體察民情。所以,從一個城市馬不停蹄地到另一個城市成了J最常做的事情。他有一個錢袋,用於存放往來城市間的路費。

聰明的J發現,如果不在某個城市停下來修整,在連續行進過程中,他所花的路費與他已走過的距離有關,在走第x千米到第x+1千米這一千米中(x是整數),他花費的路費是x+10這麼多。也就是說走1千米花費11,走2千米要花費23。

J大臣想知道:他從某一個城市出發,中間不休息,到達另一個城市,所有可能花費的路費中最多是多少呢?

輸入格式

輸入的第一行包含一個整數n,表示包括首都在內的T王國的城市數

城市從1開始依次編號,1號城市爲首都。

接下來n-1行,描述T國的高速路(T國的高速路一定是n-1條)

每行三個整數Pi, Qi, Di,表示城市Pi和城市Qi之間有一條高速路,長度爲Di千米。

輸出格式

輸出一個整數,表示大臣J最多花費的路費是多少。

樣例輸入1

5
1 2 2
1 3 1
2 4 5
2 5 4

樣例輸出1

135

輸出格式

大臣J從城市4到城市5要花費135的路費。

解題思路 

一棵樹,求任意兩點間的最大距離。 先以任意一點爲根,找到距離他最遠的點p,然後再以找到的這個點p爲根,找離p最遠的點q,p q間的距離即爲任意兩點間的距離的最大值。畫一棵樹一看就明白爲什麼了。

AC代碼

vector:

#include <bits/stdc++.h>
using namespace std;
struct Road {
	int v,w;
	Road(int vv,int ww) {
		v = vv;
		w = ww;
	}
}; 
vector <Road > r[10001];
int dis[10001];
void dfs(int nw,int pre,int d)
{
	int len = r[nw].size();
	dis[nw] = d;
	for(int i=0;i<len;i++) {
		if(r[nw][i].v == pre)
			continue;
		dfs(r[nw][i].v,nw,d+r[nw][i].w);
	}
}
int main()
{
	int n;
	scanf("%d",&n);
	int t1,t2,t3;
	for(int i=1;i<n;i++) {
		scanf("%d %d %d",&t1,&t2,&t3);
		r[t1].push_back(Road(t2,t3));
		r[t2].push_back(Road(t1,t3));
	}
	memset(dis,0,sizeof dis);
	dfs(1,-1,0);	//以1爲root 
	int root = max_element(dis+1,dis+n+1) - dis;
	memset(dis,0,sizeof dis);
	dfs(root,-1,0);
	int Max = *max_element(dis+1,dis+n+1);
	printf("%lld",Max*10+Max*(1+Max)/2);
	
}

手寫鄰接表

#include <bits/stdc++.h>
using namespace std;
struct Road {
	int v,w;
}r[20010];
void Set(int k,int v,int w)
{
	r[k].v = v;
	r[k].w = w;
}
int first[10005],next[20005];
long long dis[10005];
void dfs(int nw,int pre,int d)
{
	int NEXT = first[nw];
	dis[nw] = d;
	while(NEXT != -1 ) {
		if(r[NEXT].v != pre) {
		//	dis[r[NEXT].v] = d+r[NEXT].w;
			dfs(r[NEXT].v,nw,d+r[NEXT].w);
		}
		NEXT = next[NEXT];
	}
}
int main()
{
	int n;
	scanf("%d",&n);
	int k=0,t1,t2,t3;
	memset(first,-1,sizeof first);
	for(int i=1;i<n;i++) {
		scanf("%d %d %d",&t1,&t2,&t3);
		Set(k,t2,t3);
		next[k] = first[t1];
		first[t1] = k;
		k++;
		Set(k,t1,t3);
		next[k] = first[t2];
		first[t2] = k;
		k++;
	}
	memset(dis,0,sizeof dis); //以1爲root
	dfs(1,-1,0);
	int root = max_element(dis+1,dis+n+1) - dis;	//求距離1最遠的點號 
	memset(dis,0,sizeof dis);	
	dfs(root,-1,0);
	int Max = *max_element(dis+1,dis+n+1);
	printf("%lld",Max*10+Max*(1+Max)/2);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章