BZOJ 1631 Usaco 2007 Feb. Cow Party

【题解】

  最短路裸题。。

  本题要求出每个点到终点走最短路来回的距离,因此我们先跑一遍最短路得出每个点到终点的最短距离,然后把边反向再跑一遍最短路,两次结果之和即是答案。

  

#include<cstdio>
#include<algorithm>
#include<cstring>
#define N (2010)
#define M (200010)
#define rg register
#define fa (x>>1)
using namespace std;
int n,m,x,tot,ans,dis[N],last[N],pos[N],sum[N];
struct edge{
	int to,pre,dis;
}e[M];
struct heap{
	int to,dis;
}h[N];
struct record{
	int u,v,dis;
}rec[M];
inline int read(){
	int k=0,f=1; char c=getchar();
	while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
	while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
	return k*f;
}
inline void add(int x,int y,int z){e[++tot]=(edge){y,last[x],z}; last[x]=tot;}
inline void up(int x){
	while(x>1&&h[fa].dis>h[x].dis){
		swap(h[fa],h[x]); swap(pos[h[fa].to],pos[h[x].to]);
		x=fa;
	}
}
inline void down(int x){
	while(x<=(tot>>1)){
		int son=x<<1;
		if(son<tot&&h[son].dis>h[son+1].dis) son++;
		if(h[son].dis<h[x].dis){
			swap(h[son],h[x]); swap(pos[h[son].to],pos[h[x].to]);
			x=son;
		}
		else return;
	}
}
void dijkstra(int x){
	h[pos[x]=tot=1]=(heap){x,dis[x]=0};
	while(tot){
		int now=h[1].to; h[1]=h[tot--]; if(tot) down(1);
		for(int i=last[now],to;i;i=e[i].pre)
		if(dis[to=e[i].to]>dis[now]+e[i].dis){
			dis[to]=dis[now]+e[i].dis;
			if(!pos[to]) h[pos[to]=++tot]=(heap){to,dis[to]};
			up(pos[to]);
		}
		pos[now]=0;
	}
}
inline void clear(){
	memset(last,0,sizeof(last));
	memset(dis,32,sizeof(dis));
	memset(pos,0,sizeof(pos));
	tot=0;
}
void out(){
	for(int i=1;i<=n;i++) printf("%d ",dis[i]); puts("");
}
int main(){
	n=read(); m=read(); x=read();
	clear();
	for(rg int i=1;i<=m;i++){
		rec[i].u=read(); rec[i].v=read();
		add(rec[i].u,rec[i].v,rec[i].dis=read());
	}
	dijkstra(x); //out();
	for(int i=1;i<=n;i++) sum[i]=dis[i];
	clear();
	for(rg int i=1;i<=m;i++) add(rec[i].v,rec[i].u,rec[i].dis);
	dijkstra(x); //out();
	for(int i=1;i<=n;i++) ans=max(ans,sum[i]+dis[i]);
	printf("%d\n",ans);
	return 0;
}

  

posted @ 2018-02-02 11:22  Driver_Lao  阅读(121)  评论(0编辑  收藏  举报