[JZOJ5279]香港记者题解--最短路图

[JZOJ5279]香港记者题解--最短路图

题目链接

过 于 暴 力

分析

有一个naiive的想法就是从1到n跑最短路,中途建图,然后在图上按字典序最小走一遍,然而·这是不行的,你这样跳不一定能跳到终点.

所以应该是在1到n的最短路图上跳,怎么求有向图短路图?你跑一遍1到n得到\(dist1[]\),n到1的最短路得到\(dist[2]\),然后从1 BFS,对于原图一条\(u\),连向\(v\)的边,若\(dis1[u]+dis2[v]+dis(u,v)\)等于1到n的最短路距离,则最短路图上\(u\)\(v\)也连一条相同的边

然后模拟一遍走最小的点就好了

结果跑了个rank倒2,看他们直接倒着一遍dij就完了,现在还搞不懂为什么...

另外我用了一次DFS就直接爆栈了,全改成了BFS

代码

/*
  code by RyeCatcher
*/
const int maxn=800005;
const ll inf=1e17+19260817;
struct Edge{
	int ne,to,o;
	ll dis;
}edge[maxn<<1];
int h[maxn],num_edge=1;
inline void add_edge(int f,int to,ll c,int o){
	edge[++num_edge].ne=h[f];
	edge[num_edge].to=to;
	edge[num_edge].dis=c;
	edge[num_edge].o=o;
	h[f]=num_edge;
}
int n,m,tag[maxn];
ll dis[maxn][2],all_dis;
struct SE{
	int ne,to;
	ll dis;
}se[maxn<<1];
int sh[maxn],num_se=1;
inline void add_se(int f,int to,ll c){
	se[++num_se].ne=sh[f];
	se[num_se].to=to;
	se[num_se].dis=c;
	sh[f]=num_se;
}
bool vis[maxn];int g[maxn][2];
inline void dijsktra(int st,int id){
	Heap q;int u,v;
	for(ri i=1;i<=n;i++)dis[i][id]=inf,vis[i]=0;
	while(q.size())q.pop();
	q.push(pii(0,st));dis[st][id]=0,g[st][id]=1;
	while(q.size()){
		u=q.top().second;q.pop();
		if(vis[u])continue;
		vis[u]=1;
		for(ri i=h[u];i;i=edge[i].ne){
			v=edge[i].to;
			if(edge[i].o!=id)continue;
			if(dis[v][id]>dis[u][id]+edge[i].dis){
				dis[v][id]=dis[u][id]+edge[i].dis;
				g[v][id]=1;
				q.push(pii(dis[v][id],v));
			}
		}
	}
	return ;
}
void pre_bfs(){
	int u,v;
	queue<int> q;
	q.push(1);memset(vis,0,sizeof(vis));
	while(q.size()){
		u=q.front();q.pop();
		vis[u]=1;
		for(ri i=h[u];i;i=edge[i].ne){
			v=edge[i].to;
			if(dis[u][0]+dis[v][1]+edge[i].dis==all_dis){
				add_se(u,v,edge[i].dis);
				if(!vis[v]){
					q.push(v);
					vis[v]=1;
				}
			}
		}
	}
	return ;
}
int path[maxn],tot=0;
inline void bfs(){
	queue <int> q;
	memset(vis,0,sizeof(vis));
	q.push(1);
	int path[maxn],tot=0;
	int u,v,tt,vv,dist=0,dd;
	while(q.size()){
		u=q.front();q.pop();vis[u]=1;
		path[++tot]=tag[u];
		if(u==n){
			printf("%lld\n",all_dis);
			for(ri i=1;i<=tot;i++)printf("%d ",path[i]);
			puts("");
			exit(0);
		}
		tt=1e9+7,vv=0;
		for(ri i=sh[u];i;i=se[i].ne){
			v=se[i].to;
			if(v==n){
				vv=v,dd=se[i].dis;
				break;
			}
			if(vis[v]||!(g[v][1]&&g[v][0]))continue;
			if(tag[v]<tt){
				tt=tag[v],vv=v,dd=se[i].dis;
			}
		}
		if(!vv)break;
		q.push(vv),dist+=dd;
	}
}
int main(){
	int x,y,z;
	//freopen("journalist7.in","r",stdin);
	//freopen("wtf.out","w",stdout);
	read(n),read(m);
	for(ri i=1;i<=n;i++){
		read(tag[i]);
	}
	for(ri i=1;i<=m;i++){
		read(x),read(y),read(z);
		add_edge(x,y,z,0);
		add_edge(y,x,z,1);
	}
	dijsktra(1,0),dijsktra(n,1);
	all_dis=dis[n][0];
	pre_bfs();
	bfs();
	return 0;
}

posted @ 2018-10-31 16:05  Rye_Catcher  阅读(196)  评论(0编辑  收藏  举报