HDU1535:最短路

HDU1535

题意:从1号车站到所有车站,再从所有车站到1号,花费总和最少为多少?注意公交车是单向的。

题解:从1到所有车站就一次dijkstra,然后回来怎么做呢?就是把所有的路反向,再走一次dijkstra。这样子原先你可以从1到其它结点的路不可以走了,但是从其它结点到1的路就通了。

内存有点紧G++内存超了,但C++AC

标准的FIFO的Dijkstra代码(MLE)

#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <functional>
#include <cstdio>
#include <iostream>
using namespace std;
int const N = 1000000 + 10;
typedef long long ll;
typedef pair<ll,int>pli;
ll const inf = 0x7f7f7f7f;
int n,m;
ll dis[N];
struct Edge
{
	int from,to;
	ll dist;
	Edge(){};
	Edge(int ff,int tt,ll dd):from(ff),to(tt),dist(dd){};
};
vector<Edge>G1[N],G2[N];
priority_queue<pli,vector<pli>,greater<pli> >q;
ll Dijkstra(vector<Edge>G[N]){
	for(int i=1;i<=n;i++)	dis[i] = inf;
	dis[1] = 0;
	q.push(make_pair(0,1));
	while(!q.empty()){
		pli p = q.top();	q.pop();
		int u = p.second;
		if(dis[u] < p.first)	continue;
		for(int i=0;i<G[u].size();i++){
			Edge e = G[u][i];
			if(dis[e.to] > dis[e.from] + e.dist){
				dis[e.to] = dis[e.from] + e.dist;
				q.push(make_pair(dis[e.to],e.to));
			}
		}
	}
	ll sum = 0;
	for(int i=1;i<=n;i++)	sum += dis[i];
	return sum;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);   //n表示车站的数量,m表示线路的数量
		for(int i=1;i<=n;i++)	G1[i].clear(),G2[i].clear();
		for(int i=1;i<=m;i++){
			int from,to;
			ll dist;
			scanf("%d%d%lld",&from,&to,&dist);
			G1[from].push_back(Edge(from,to,dist));
			G2[to].push_back(Edge(to,from,dist));
		}
		ll sum = Dijkstra(G1);
		sum += Dijkstra(G2);
		cout<<sum<<endl;
	}
	return 0;
}

优化了一下,把pair去掉了,边结构体去掉了头结点

#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#include <functional>
#include <cstdio>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
const int N = 1000000 + 10;
int n,m,dis[N],vis[N];
struct Node{
	int u,len;
	Node(){};
	Node(int uu=0,int ll=0):u(uu),len(ll){};
	bool operator < (const Node &a)const{
		return len > a.len;
	}
};
vector<Node>G1[N],G2[N];
int Dijkstra(vector<Node>G[]){
	memset(vis,0,sizeof(vis));
	for(int i=0;i<=n;i++)	dis[i] = inf;
	dis[1] = 0;
	priority_queue<Node>q;
	q.push(Node(1,0));
	while(!q.empty()){
		Node p = q.top();	q.pop();
		int v = p.u;
		if(vis[v])	continue;
		vis[v] = 1;
		for(int i=0;i<G[v].size();i++){
			Node e = G[v][i];
			if(vis[e.u])	continue;
			if(dis[e.u] > dis[v] + e.len){
				dis[e.u] = dis[v] + e.len;
				q.push(Node(e.u,dis[e.u]));
			}
		}
	}
	int sum = 0;
	for(int i=1;i<=n;i++)	sum += dis[i];
	return sum;
}
int main(){
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&n,&m);   //n表示车站的数量,m表示线路的数量
		for(int i=0;i<=n;i++)	G1[i].clear(),G2[i].clear();
		for(int i=0;i<m;i++){
			int from,to,dist;
			scanf("%d%d%d",&from,&to,&dist);
			G1[from].push_back(Node(to,dist));
			G2[to].push_back(Node(from,dist));
		}
		int sum = Dijkstra(G1);
		sum += Dijkstra(G2);
		cout<<sum<<endl;
	}
	return 0;
}

 

posted @ 2019-02-13 21:17  月光下の魔术师  阅读(5)  评论(0)    收藏  举报