[洛谷P1342]请柬

题目大意:有n个站,和m条单向边,每条边有乘车价值,保证汽车能开回来。有n-1个学生从1出发,分别到n-1个不同的点,然后回来。求最少的总价值。

解题思路:最短路,求回来的最少价值其实可以建立反向图,然后跑最短路即可。一共两遍最短路,我用堆优化Dijkstra算法,时间复杂度$O(mlog n)$。

注意long long。

pbds大法好!

C++ Code:

#include<ext/pb_ds/priority_queue.hpp>
#include<cstdio>
#include<cstring>
#define N (1000000+10)
#define C c=getchar()
int head[2][N<<1],nxt[2][N<<1],to[2][N<<1],n,m,cnt;
long long dis[2][N<<1],ans[N];
inline int readint(){
    char C;
    while(!isdigit(c))C;
    int p=0;
    while(isdigit(c))p=(p<<3)+(p<<1)+(c^'0'),C;
    return p;
}
struct heapnode{
	long long d;int u;
	bool operator <(const heapnode& rhs)const{return d>rhs.d;}
};
__gnu_pbds::priority_queue<heapnode>Q;
void dijkstra(int p){
	memset(ans,0x3f,sizeof(ans));
	ans[1]=0;
	Q.push((heapnode){0,1});
	while(!Q.empty()){
		heapnode x=Q.top();Q.pop();
		int u=x.u;
		if(ans[u]!=x.d)continue;
		for(int i=head[p][u];i;i=nxt[p][i]){
			int v=to[p][i];
			if(ans[v]>ans[u]+dis[p][i]){
				ans[v]=ans[u]+dis[p][i];
				Q.push((heapnode){ans[v],v});
			}
		}
	}
}
int main(){
	n=readint(),m=readint();
	cnt=0;
	while(m--){
		int x=readint(),y=readint(),d=readint();
		++cnt;
		to[0][cnt]=y;
		dis[0][cnt]=d;
		nxt[0][cnt]=head[0][x];
		head[0][x]=cnt;
		to[1][cnt]=x;
		dis[1][cnt]=d;
		nxt[1][cnt]=head[1][y];
		head[1][y]=cnt;
	}
	long long Answer=0;
	for(int i=0;i<2;++i){
		dijkstra(i);
		for(int j=2;j<=n;++j)Answer+=ans[j];
	}
	printf("%lld
",Answer);
	return 0;
}
原文地址:https://www.cnblogs.com/Mrsrz/p/7392079.html