把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

【最短路-拆点】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;
}

posted @ 2020-11-05 16:33  Starlight_Glimmer  阅读(108)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end