牛客网 旅行商问题 堆优化dijstr

链接:https://ac.nowcoder.com/acm/contest/547/E
来源:牛客网
 

题目描述

旅行商来到了一个新的国家,这个国家有N个城市,他们直接由N-1条道路相连接,每条道路的长度不尽相同

旅行商现在在1号城市,若他要每一个城市都游览一遍,他需要行走的最短路程是多少?

题解;城市很多,朴素地dijstra 存不下图,用堆优化的dij;  然后就是每个城市都走还要求最短路程  那就把最长的的一段路走一遍,其余路走两遍,(因为还有返回啊)  (文中加粗意思是题中给出的数据就是每两点间的边值且唯一!!)

vector存图   牛客数据最后跑了85+ ~ 100+ms

#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<queue>
#include<vector>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000000;
typedef pair<int,int> p;
vector<p> e[maxn];
int dis[maxn];
int n;
void dij(int s){
	priority_queue<p,vector<p>, greater<p> > q;  
	dis[s]=0;
	q.push(make_pair(s,dis[s]));
	while(!q.empty()){
		pair<int,int>tmp;
		tmp=q.top();
		q.pop();
		int u=tmp.first;
		int size=e[u].size();
		for(int i=0;i<size;i++){
			int v=e[u][i].first;
			if(dis[v]>dis[u]+e[u][i].second){
				dis[v]=dis[u]+e[u][i].second;	
			  q.push(make_pair(v,dis[v]));
			}
		}	
    }
}
int main(){
	cin>>n;
	int m=n-1;
	for(int i=0;i<=n;i++){
		dis[i]=inf;
		e[i].clear();
	}
	int sum=0;
	while(m--){
		int x,y,z;
		cin>>x>>y>>z;
		sum+=z;
		e[x].push_back(make_pair(y,z));
		e[y].push_back(make_pair(x,z));
	}
	
	dij(1);
	
	int mxx=0;
	for(int i=1;i<=n;i++){
	//	cout<<dis[i]<<" ";
		mxx=max(mxx,dis[i]);
	}
	//cout<<endl;
	cout<<sum*2-mxx<<endl;
}

 邻接表存图  跑了 37ms!!    可能领接表跑图快?还是加了VIS数组呐

#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<queue> 
using namespace std;
const int maxn=1000005;
const int inf=0x3f3f3f3f;
struct Edge{
	int v,w;//w为距离 
	int next;
};
Edge edge[maxn];//边编号  从1开始   
struct qnode{    //堆优化 
     int u;	//起点 
     int w;//距离
     
   qnode(int u=0,int w=0):u(u),w(w){}//构造函数 
  
	bool operator < (const qnode& a) const{//重载小于号 
	return w>a.w;
	} 
};
int dis[maxn];
int head[maxn];
bool vis[maxn];
int x[maxn],y[maxn],z[maxn];
int n,m;
int size; 
void add_edge(int u,int v,int w){//邻接表加边 
	  edge[size].v=v;
	  edge[size].w=w;
	  edge[size].next=head[u];
	  head[u]=size;
	  size++; 
}
void dijkstra(int s){
	priority_queue<qnode>q;
	while(!q.empty())
	q.pop();
	
    q.push(qnode(s,0));
	dis[s]=0;

	while(!q.empty()){
		qnode t=q.top();
		q.pop();
		int u=t.u;
		if(vis[u])continue;
		vis[u]=true;//找到一个点就标记一次 
		for(int i=head[u];i!=-1;i=edge[i].next){
			int v=edge[i].v;
			int w=edge[i].w; 
			if(!vis[v]&&dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push(qnode(v,dis[v]));//存到队堆里会自动利用堆 进行排序; 
			} 
		}	
	}
}
int main(){
	size=1;	
	scanf("%d",&n);
	for(int i=0;i<=n;i++){//初始化 
		head[i]=-1;
		dis[i]=inf;
		vis[i]=false; 
	}
	m=n-1;
	int sum=0;
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&x[i],&y[i],&z[i]);	
		sum+=z[i];
	}	
	for(int i=1;i<=m;i++){
		add_edge(x[i],y[i],z[i]);
		add_edge(y[i],x[i],z[i]);
	}
	
    dijkstra(1);
    int mxx=0;
	for(int i=1;i<=n;i++){
	//	cout<<dis[i]<<" ";
		mxx=max(mxx,dis[i]);
	}
	//cout<<endl;
	cout<<sum*2-mxx<<endl;
	return 0;
}
	  

猜你喜欢

转载自blog.csdn.net/gml1999/article/details/88614324