Evanyou Blog 彩带

洛谷P1342请柬

传送门啦

核心思想:两遍最短路.

1号点去各地的时间直接套最短路模板,各地到1号点时间用逆向思维,视为求1号点沿反边到各地的时间即可.

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define re register
using namespace std;
const int maxn = 1000005;

inline int read(){
	char ch = getchar();
	int f = 1 , x = 0;
	while(ch > '9' || ch < '0'){if(ch == '-')f = -1;ch = getchar();}
	while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
	return x * f;
}

int n,m,u,v;
long long w;
int head1[maxn],tot1,head2[maxn],tot2;
long long ans,dis1[maxn],dis2[maxn];

struct Edge{
	int from,to,next;
	long long val;
}edge1[maxn<<1] , edge2[maxn<<1];

struct Node{
	int u,d;
	bool operator < (const Node &f) const {
		return d > f.d;
	}
};

inline void add1(int u,int v,long long w){
	edge1[++tot1].from = u;
	edge1[tot1].to = v;
	edge1[tot1].val = w;
	edge1[tot1].next = head1[u];
	head1[u] = tot1;
}

inline void add2(int u,int v,long long w){
	edge2[++tot2].from = u;
	edge2[tot2].to = v;
	edge2[tot2].val = w;
	edge2[tot2].next = head2[u];
	head2[u] = tot2;
}

inline void dijk1(int s){
	for(re int i=1;i<=n;i++)  dis1[i] = 1e9;
	priority_queue<Node> q;
	dis1[s] = 0;
	q.push((Node) {s , dis1[s]});
	while(!q.empty()){
		Node cur = q.top();
		q.pop();
		int d = cur.d , u = cur.u;
		if(d != dis1[u]) continue;
		for(re int i=head1[u];i;i=edge1[i].next){
			int v = edge1[i].to;
			if(dis1[v] > dis1[u] + edge1[i].val){
				dis1[v] = dis1[u] + edge1[i].val;
				q.push((Node) {v , dis1[v]});
			}
		}
	}
}

inline void dijk2(int s){
	for(re int i=1;i<=n;i++)  dis2[i] = 1e9;
	priority_queue<Node> q;
	dis2[s] = 0;
	q.push((Node) {s , dis2[s]});
	while(!q.empty()){
		Node cur = q.top();
		q.pop();
		int d = cur.d , u = cur.u;
		if(d != dis2[u]) continue;
		for(re int i=head2[u];i;i=edge2[i].next){
			int v = edge2[i].to;
			if(dis2[v] > dis2[u] + edge2[i].val){
				dis2[v] = dis2[u] + edge2[i].val;
				q.push((Node) {v , dis2[v]});
			}
		}
	}
}

int main(){
	n = read(); m = read();
	for(int i=1;i<=m;i++){
		u = read(); v = read(); scanf("%lld",&w);
		add1(u , v , w);
		add2(v , u , w);
	}
	dijk1(1);
	for(int i=2;i<=n;i++)
		ans += dis1[i];
	dijk2(1);	
	for(int i=n;i>=2;i--){	
		ans += dis2[i];
	}
	printf("%lld\n",ans);
	return 0;
}
posted @ 2018-11-05 14:12  Stephen_F  阅读(80)  评论(0编辑  收藏  举报