【JZOJ6419】模擬旅行&【BZOJ5506】【luoguP5304】旅行者

description

某國有n座城市,這些城市之間通過m條單向道路相連,已知每條道路的長度。
不過,小X只對其中k座城市感興趣。
爲了更好地規劃模擬旅行路線,提升模擬旅行的體驗,小X想要知道他感興趣的城市之間兩兩最短路的最小值(即在他感興趣的城市中,最近的一對的最短距離)。
作爲一個肥宅,小X根本懶得寫程序來解決這道問題,於是他把這個問題丟給了你。


J 國有 nn 座城市,這些城市之間通過 mm 條單向道路相連,已知每條道路的長度。

一次,居住在 J 國的 Rainbow 邀請 Vani 來作客。不過,作爲一名資深的旅行者,Vani 只對 J 國的 kk 座歷史悠久、自然風景獨特的城市感興趣。
爲了提升旅行的體驗,Vani 想要知道他感興趣的城市之間「兩兩最短路」的最小值(即在他感興趣的城市中,最近的一對的最短距離)。

也許下面的劇情你已經猜到了——Vani 這幾天還要忙着去其他地方遊山玩水,就請你幫他解決這個問題吧。


analysis

  • 對於所有關鍵點開始跑最短路,原圖和反圖分別跑一次,記爲disi,dis1idis_i,dis1_i

  • 記錄下dijdij裏每個點從哪一個關鍵點轉移得來,記爲fromi,from1ifrom_i,from1_i

  • 枚舉一條邊,如果邊的兩端點的fromxfromyfrom_x≠from_y,此時可以拿disx+dis1y+lendis_x+dis1_y+len更新答案

  • 因爲fromxfromyfrom_x≠from_y,所以兩端點是從不同關鍵點走到,說明該邊可能在兩個關鍵點的最短路上


  • 還有一種更妙的做法,不過SPFASPFA弄不了,我還沒實現

  • 建立超級源向所有關鍵點連00邊,然後從超級源跑最短路和次短路

  • 關鍵點的最短路當然是00,次短路的意義是什麼呢

  • 其實某關鍵點的次短路一定是經過另一個關鍵點走到它的最短路

  • 答案取次短路的最小值就可以了,感覺確實妙


code

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define MAXN 300005
#define MAXM 3000005
#define ha 1926081719491001
#define ll long long
#define reg register ll
#define max(x,y) ((x>y)?(x):(y))
#define min(x,y) ((x<y)?(x):(y))
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define rep(i,a) for (reg i=last[a];i;i=next[i])
#define rep1(i,a) for (reg i=last1[a];i;i=next1[i])

using namespace std;

ll last[MAXM],next[MAXM],tov[MAXM],len[MAXM];
ll last1[MAXM],next1[MAXM],tov1[MAXM],len1[MAXM];
ll a[MAXN],dis[MAXN],dis1[MAXN],from[MAXN],from1[MAXN];
ll n,m,k,tot,tot1,ans=ha;
ll edge[MAXM][3];
bool bz[MAXN];

struct node
{
	ll x,y;
	bool operator<(const node &a)const{return a.y<y;}
};
priority_queue<node>q;

inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
inline void link(ll x,ll y,ll z){next[++tot]=last[x],last[x]=tot,tov[tot]=y,len[tot]=z;}
inline void link1(ll x,ll y,ll z){next1[++tot1]=last1[x],last1[x]=tot1,tov1[tot1]=y,len1[tot1]=z;}
inline void dijkstra()
{
	memset(dis,100,sizeof(dis));
	memset(bz,0,sizeof(bz));
	fo(i,1,k)q.push((node){a[i],dis[a[i]]=0}),from[a[i]]=a[i];
	while (!q.empty())
	{
		node now=q.top();q.pop();
		if (bz[now.x])continue;bz[now.x]=1;
		rep(i,now.x)if (dis[now.x]+len[i]<dis[tov[i]])
		{
			dis[tov[i]]=dis[now.x]+len[i],from[tov[i]]=from[now.x];
			q.push((node){tov[i],dis[tov[i]]});
		}
	}
}
inline void dijkstra1()
{
	memset(dis1,100,sizeof(dis1));
	memset(bz,0,sizeof(bz));
	fo(i,1,k)q.push((node){a[i],dis1[a[i]]=0}),from1[a[i]]=a[i];
	while (!q.empty())
	{
		node now=q.top();q.pop();
		if (bz[now.x])continue;bz[now.x]=1;
		rep1(i,now.x)if (dis1[now.x]+len1[i]<dis1[tov1[i]])
		{
			dis1[tov1[i]]=dis1[now.x]+len1[i],from1[tov1[i]]=from1[now.x];
			q.push((node){tov1[i],dis1[tov1[i]]});
		}
	}
}
int main()
{
	freopen("tour.in","r",stdin);
	freopen("tour.out","w",stdout);
	n=read(),m=read(),k=read();
	fo(i,1,m)
	{
		ll x=read(),y=read(),z=read();
		edge[i][0]=x,edge[i][1]=y,edge[i][2]=z;
		link(x,y,z),link1(y,x,z);
	}
	fo(i,1,k)a[i]=read();
	dijkstra(),dijkstra1();
	fo(i,1,m)if (from[edge[i][0]]!=from1[edge[i][1]])
		ans=min(ans,dis[edge[i][0]]+dis1[edge[i][1]]+edge[i][2]);
	printf("%lld\n",ans);
	return 0;
}
#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#define MAXN 300005
#define MAXM 3000005
#define ha 1926081719491001
#define ll long long
#define reg register ll
#define max(x,y) ((x>y)?(x):(y))
#define min(x,y) ((x<y)?(x):(y))
#define fo(i,a,b) for (reg i=a;i<=b;++i)
#define fd(i,a,b) for (reg i=a;i>=b;--i)
#define rep(i,a) for (reg i=last[a];i;i=next[i])
#define rep1(i,a) for (reg i=last1[a];i;i=next1[i])

using namespace std;

ll last[MAXM],next[MAXM],tov[MAXM],len[MAXM];
ll last1[MAXM],next1[MAXM],tov1[MAXM],len1[MAXM];
ll a[MAXN],dis[MAXN],dis1[MAXN],from[MAXN],from1[MAXN];
ll n,m,k,T,tot,tot1,ans=ha;
ll edge[MAXM][3];
bool bz[MAXN];

struct node
{
	ll x,y;
	bool operator<(const node &a)const{return a.y<y;}
};
priority_queue<node>q;

inline ll read()
{
	ll x=0,f=1;char ch=getchar();
	while (ch<'0' || '9'<ch){if (ch=='-')f=-1;ch=getchar();}
	while ('0'<=ch && ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*f;
}
inline void link(ll x,ll y,ll z){next[++tot]=last[x],last[x]=tot,tov[tot]=y,len[tot]=z;}
inline void link1(ll x,ll y,ll z){next1[++tot1]=last1[x],last1[x]=tot1,tov1[tot1]=y,len1[tot1]=z;}
inline void dijkstra()
{
	memset(dis,100,sizeof(dis));
	memset(bz,0,sizeof(bz));
	fo(i,1,k)q.push((node){a[i],dis[a[i]]=0}),from[a[i]]=a[i];
	while (!q.empty())
	{
		node now=q.top();q.pop();
		if (bz[now.x])continue;bz[now.x]=1;
		rep(i,now.x)if (dis[now.x]+len[i]<dis[tov[i]])
			dis[tov[i]]=dis[now.x]+len[i],from[tov[i]]=from[now.x],q.push((node){tov[i],dis[tov[i]]});
	}
}
inline void dijkstra1()
{
	memset(dis1,100,sizeof(dis1));
	memset(bz,0,sizeof(bz));
	fo(i,1,k)q.push((node){a[i],dis1[a[i]]=0}),from1[a[i]]=a[i];
	while (!q.empty())
	{
		node now=q.top();q.pop();
		if (bz[now.x])continue;bz[now.x]=1;
		rep1(i,now.x)if (dis1[now.x]+len1[i]<dis1[tov1[i]])
			dis1[tov1[i]]=dis1[now.x]+len1[i],from1[tov1[i]]=from1[now.x],q.push((node){tov1[i],dis1[tov1[i]]});
	}
}
int main()
{
	T=read();
	while (T--)
	{
	memset(last,0,sizeof(last)),memset(last1,0,sizeof(last1));
	memset(next,0,sizeof(next)),memset(next1,0,sizeof(next1));
	memset(tov,0,sizeof(tov)),memset(tov1,0,sizeof(tov1)),tot=0;
	memset(len,0,sizeof(len)),memset(len1,0,sizeof(len1)),tot1=0;
	memset(from,0,sizeof(from)),memset(from1,0,sizeof(from1));
	n=read(),m=read(),k=read(),ans=ha;
	fo(i,1,m)
	{
		ll x=read(),y=read(),z=read();
		edge[i][0]=x,edge[i][1]=y,edge[i][2]=z;
		link(x,y,z),link1(y,x,z);
	}
	fo(i,1,k)a[i]=read();
	dijkstra(),dijkstra1();
	fo(i,1,m)if (from[edge[i][0]]!=from1[edge[i][1]])
		ans=min(ans,dis[edge[i][0]]+dis1[edge[i][1]]+edge[i][2]);
	printf("%lld\n",ans);
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章