历届试题 大臣的旅费

//内存没开够会运行错误,开够了  就超时了....以下第一个只有75分,改成和两次Dfs差不多的形式(即两次bfs)就可以了,感觉  我的这个有点像迪杰斯特拉或者SPFA(当时是照着用vector模拟邻接表做的,刚好里面求得是最短路径,,然后  按他的说法,是属于SPFA,,具体的我不清楚).......但是   求得 是最长路径.....不过感觉这种写着没有直接DFS(直接更新起始点到目前所到点的距离)来的简洁。。。。

用两次求得最长路径的思想是:https://blog.csdn.net/llwwlql/article/details/53914447 

1) 如果w 是直径上的点,则v显然是直径的终点(因为如果v不是的话,则必定存在另一个点x使得w到x的距离更长,则与d(u,v)为直径冲突)

2)如果w不是直径上的点,则w到v必然于树的直径相交(反证),那么交点到v 必然就是直径的后半段了,所以v一定是直径的一个端点,所以从v进行DFS得到的一定是直径长度

 


#include<iostream>
#include<cstdio>
#include<string.h>
#include<queue>
#include<vector>
#include<algorithm>
 
using namespace std;

const int N = 10000+5;
const int inf = 0x3f3f3f;

struct Node{
		int u, v, w;
}dis[N];

bool cmp(Node a, Node b){
		return a.w < b.w;
}
vector<Node> Head[N];
bool vis[N];
	int n;

//初始化
void init()
{
	for(int i=1; i<N; i++){
		dis[i].v = i;
		dis[i].u = i;
		dis[i].w = 0;
	}
	
	for(int i=1; i<N; i++){
		vis[i] = false;
	}
 } 

//构造邻接表 
void AddEdge(int u, int v, int w)
{
	Node tmp;
	
	tmp.v = v, tmp.w = w;
	
	Head[u].push_back(tmp);
}

void UpdateDis()
{
	int MAX = 0;
	
for(int i=1; i<=n; i++)
{
	
	queue<int> q;

	init();
	

	q.push(i);
	
	dis[i].w = 0;
	vis[i] = true;
	
	while(!q.empty()){
	
		int tmp = q.front();
		q.pop();
		
		for(int i=0; i<Head[tmp].size(); i++){
	
			int u = tmp, v = Head[tmp].at(i).v, w = Head[tmp].at(i).w;
			
			if(!vis[v] && dis[v].w < dis[u].w + w){//求最长的距离 
				
				dis[v].w = dis[u].w+w;
				dis[u].v = v; 
	//			dis[u].u = u;
				
				//if(!vis[v])
				{
					vis[v] = true;
					q.push(v);
				}
			}
			
		}
	}		
	sort(dis+1, dis+1+n, cmp);
	MAX = max(MAX, dis[n].w);
//	cout << dis[n].u <<" " << dis[n].v <<" " << dis[n].w << endl;
}
	cout << MAX*10+(MAX+1)*MAX/2 << endl;


}

int main()
{
	
	cin >> n;
	
	for(int i=1; i<n; i++){
		
		int a, b, c;
		
		cin >> a >> b >> c;
		
		AddEdge(a, b, c);
		AddEdge(b, a, c);
	}
	
	UpdateDis();
	
	return 0;
 }
 

AC代码

//https://blog.csdn.net/llwwlql/article/details/53914447 两次dfs求出树的直径 





#include<iostream>
#include<cstdio>
#include<string.h>
#include<queue>
#include<vector>
#include<algorithm>
 
using namespace std;

const int N = 10000+5;
const int inf = 0x3f3f3f;

struct Node{
		int u, v, w;
}dis[N];

bool cmp(Node a, Node b){
		return a.w < b.w;
}
vector<Node> Head[N];
bool vis[N];
	int n;

//初始化
void init()
{
	for(int i=1; i<N; i++){
		dis[i].v = i;
		dis[i].u = i;
		dis[i].w = 0;
	}
	
	for(int i=1; i<N; i++){
		vis[i] = false;
	}
 } 

//构造邻接表 
void AddEdge(int u, int v, int w)
{
	Node tmp;
	
	tmp.v = v, tmp.w = w;
	
	Head[u].push_back(tmp);
}

void UpdateDis(int i)
{
	int MAX = 0;
	
//for(int i=1; i<=n; i++)
{
	
	queue<int> q;

	init();
	
	q.push(i);
	
	dis[i].w = 0;
	vis[i] = true;
	
	while(!q.empty()){
	
		int tmp = q.front();
		q.pop();
		
		for(int i=0; i<Head[tmp].size(); i++){
	
			int u = tmp, v = Head[tmp].at(i).v, w = Head[tmp].at(i).w;
			
			if(!vis[v] && dis[v].w < dis[u].w + w){//求最长的距离 
				
				dis[v].w = dis[u].w+w;
				dis[u].v = v; 
	//			dis[u].u = u;
				
				//if(!vis[v])
				{
					vis[v] = true;
					q.push(v);
				}
			}
			
		}
	}		
	sort(dis+1, dis+1+n, cmp);
//	MAX = max(MAX, dis[n].w);
//	cout << dis[n].u <<" " << dis[n].v <<" " << dis[n].w << endl;
}
//	cout << MAX*10+(MAX+1)*MAX/2 << endl;


}

int main()
{
	
	cin >> n;
	
	for(int i=1; i<n; i++){
		
		int a, b, c;
		
		cin >> a >> b >> c;
		
		AddEdge(a, b, c);
		AddEdge(b, a, c);
	}
	
	UpdateDis(1);
	
	int start = dis[n].v;
	
	UpdateDis(start);
	
	int MAX = dis[n].w;
	cout << MAX*10+(MAX+1)*MAX/2 << endl;
	
	return 0;
 }
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值