[AHOI2017初中组]guide 题解

题面

我们无论怎么走,都是要从此点沿最短路径走到终点,所以我们以n为原点跑两边dijkstra就可以了;

而抱怨数可以根据之前跑出来的东西新建一个图,然后跑最短路就好了;

#include <bits/stdc++.h>
#define inc(i,a,b) for(register int i=a;i<=b;i++)
using namespace std;
int head[2000010],cnt;
class littlestar{
	public:
		int to;
		int nxt;
		int w1,w2;
		int w;
		void add(int u,int v,int gg1,int gg2){
			to=v;
			nxt=head[u];
			w1=gg1; w2=gg2;
			head[u]=cnt;
		}
}star[2000010];
int n,m;
priority_queue<pair<int,int> > q;
int dis[2000010],vis[2000010];
void dijkstra1()
{
	memset(dis,0x3f,sizeof(dis));
	q.push(make_pair(0,n));
	dis[n]=0;
	while(q.size()){
		int u=q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=head[u];i;i=star[i].nxt){
			int v=star[i].to;
			if(dis[v]>dis[u]+star[i].w1){
				dis[v]=dis[u]+star[i].w1;
				q.push(make_pair(-dis[v],v));
			}
		}
	}
}
int dis2[2000010];
void dijkstra2()
{
	memset(vis,0,sizeof(vis));
	memset(dis2,0x3f,sizeof(dis2));
	q.push(make_pair(0,n));
	dis2[n]=0;
	while(q.size()){
		int u=q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=head[u];i;i=star[i].nxt){
			int v=star[i].to;
			if(dis2[v]>dis2[u]+star[i].w2){
				dis2[v]=dis2[u]+star[i].w2;
				q.push(make_pair(-dis2[v],v));
			}
		}
	}
}
void dijkstra()
{
	memset(vis,0,sizeof(vis));
	memset(dis2,0x3f,sizeof(dis2));
	q.push(make_pair(0,n));
	dis2[n]=0;
	while(q.size()){
		int u=q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(int i=head[u];i;i=star[i].nxt){
			int v=star[i].to;
			if(dis2[v]>dis2[u]+star[i].w){
				dis2[v]=dis2[u]+star[i].w;
				q.push(make_pair(-dis2[v],v));
			}
		}
	}
}
int main()
{
	cin>>n>>m;
	inc(i,1,m){
		int a,b,p,q;
		scanf("%d%d%d%d",&a,&b,&p,&q);
		star[++cnt].add(b,a,p,q);
	}
	dijkstra1();		
	dijkstra2();
	inc(u,1,n){
		for(int i=head[u];i;i=star[i].nxt){
			int v=star[i].to;
			if(dis[v]!=dis[u]+star[i].w1) ++star[i].w;
			if(dis2[v]!=dis2[u]+star[i].w2) ++star[i].w;
		}
	}
	dijkstra();
	cout<<dis2[1];
}
原文地址:https://www.cnblogs.com/kamimxr/p/11751218.html