• 【JZOJ6419】模拟旅行&【BZOJ5506】【luoguP5304】旅行者


    description

    某国有n座城市,这些城市之间通过m条单向道路相连,已知每条道路的长度。
    不过,小X只对其中k座城市感兴趣。
    为了更好地规划模拟旅行路线,提升模拟旅行的体验,小X想要知道他感兴趣的城市之间两两最短路的最小值(即在他感兴趣的城市中,最近的一对的最短距离)。
    作为一个肥宅,小X根本懒得写程序来解决这道问题,于是他把这个问题丢给了你。


    J 国有 nn 座城市,这些城市之间通过 mm 条单向道路相连,已知每条道路的长度。

    一次,居住在 J 国的 Rainbow 邀请 Vani 来作客。不过,作为一名资深的旅行者,Vani 只对 J 国的 kk 座历史悠久、自然风景独特的城市感兴趣。
    为了提升旅行的体验,Vani 想要知道他感兴趣的城市之间「两两最短路」的最小值(即在他感兴趣的城市中,最近的一对的最短距离)。

    也许下面的剧情你已经猜到了——Vani 这几天还要忙着去其他地方游山玩水,就请你帮他解决这个问题吧。


    analysis

    • 对于所有关键点开始跑最短路,原图和反图分别跑一次,记为(dis_i,dis1_i)

    • 记录下(dij)里每个点从哪一个关键点转移得来,记为(from_i,from1_i)

    • 枚举一条边,如果边的两端点的(from_x≠from_y),此时可以拿(dis_x+dis1_y+len)更新答案

    • 因为(from_x≠from_y),所以两端点是从不同关键点走到,说明该边可能在两个关键点的最短路上


    • 还有一种更妙的做法,不过(SPFA)弄不了,我还没实现

    • 建立超级源向所有关键点连(0)边,然后从超级源跑最短路和次短路

    • 关键点的最短路当然是(0),次短路的意义是什么呢

    • 其实某关键点的次短路一定是经过另一个关键点走到它的最短路

    • 答案取次短路的最小值就可以了,感觉确实妙


    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
    ",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
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    NOIP 模拟 序列操作
    LUOGU 1525 关押罪犯
    HDU2473 Junk-Mail Filter
    BZOJ 2096 Pilots
    luogu 3939 数颜色
    NOIP模拟 赌博游戏
    Unity3D
    HTML5
    Cocos2d-x——支持多触点
    Cocos2d-x——Cocos2d-x 屏幕适配总结
  • 原文地址:https://www.cnblogs.com/horizonwd/p/11840134.html
Copyright © 2020-2023  润新知