1. 程式人生 > 實用技巧 >【最短路-拆點】ARC061Cすぬけ君の地下鉄旅行/Snuke's Subway Trip

【最短路-拆點】ARC061Cすぬけ君の地下鉄旅行/Snuke's Subway Trip

題目連結

題目解析

剛開始想的是分層圖,同個公司的邊是同一層。走的時候你可以在同一層隨便亂走,然後可以跑到另外一層的對應點去,這需要\(1\)的花費。

所以可以想到如下建邊方式:每一層之間的邊的邊權為\(0\),同一個點的任意兩層的點之間邊權為\(1\),即表示換乘的花費為\(1\)

發現這樣建邊邊數會很多,比如一條邊在\(i\)層都出現過 那麼這個點就要建\(\frac {i(i-1)}{2}\)條邊。

可以整一個虛點把每一層的點都連在一起,相當於搞一個換乘站點出來。
每個點換乘到另一個層的點需要經過\(2\)條邊 所以每個點到換乘點的邊權為\(0.5\)
避免浮點運算 所以最後除以\(2\)

就可以了

後來還發現了一種更加簡單暴力的方法:就是在做最短路的時候,判斷一下,如果前驅邊和這條邊的公司一樣,那麼費用就是\(0\),否則為\(1\)(記錄的東西變多了)不過這個我沒有寫qwq


►Code View

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<ctime>
#include<map>
using namespace std;
#define N 1000005
#define LL long long
#define INF 0x3f3f3f3f
#define inf 0x7fffffff
int rd()
{
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48); c=getchar();}
	return f*x;
}
int n,m,s;
int c[N],tot;//對公司編號進行離散化 
vector<pair<int,LL> >G[N];
LL d[N];
priority_queue< pair<LL,int>, vector< pair<LL,int> >,greater<pair<LL,int> > >Q;
map<pair<int,int>,int> mp;//編號為i的在第j個網路裡的點的編號
struct node{
	int u,v,com;
}e[N];
int iden;//點的編號 
void Init()
{
    while(!Q.empty())
        Q.pop();
    memset(d,0x7f,sizeof(d));
}
void dijkstra()
{
    Init();
    d[s]=0;Q.push(make_pair(0,s));
    while(!Q.empty())
    {
        pair<LL,int> tmp=Q.top();
        Q.pop();
        int u=tmp.second;
        if(tmp.first>d[u]) continue;
        for(int i=0;i<G[u].size();i++)
        {
            int v=G[u][i].first; LL w=G[u][i].second;
            if(d[v]>d[u]+w)
            {
                d[v]=d[u]+w;
                Q.push(make_pair(d[v],v));
            }
        }
    }
}
int ID(int x,int y)
{
	if(mp.find(make_pair(x,y))!=mp.end())
		return mp[make_pair(x,y)];
	return mp[make_pair(x,y)]=++iden;
}
int main()
{
	n=rd(),m=rd();
	for(int i=1;i<=m;i++)
	{
		int u=rd(),v=rd(),id=rd();
		if(!c[id]) c[id]=++tot;
		e[i].u=u,e[i].v=v,e[i].com=c[id];
	}
	iden=n; 
	for(int i=1;i<=m;i++)
	{
		int u=ID(e[i].u,e[i].com),v=ID(e[i].v,e[i].com);
		G[u].push_back(make_pair(v,0));
		G[v].push_back(make_pair(u,0));
		G[e[i].u].push_back(make_pair(u,1));
		G[u].push_back(make_pair(e[i].u,1));
		G[e[i].v].push_back(make_pair(v,1));
		G[v].push_back(make_pair(e[i].v,1));
	}
	s=1;
    dijkstra();
    if(d[n]>=INF) puts("-1");
    else printf("%lld\n",d[n]/2);
    return 0;
}