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

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

题目链接

题目解析

刚开始想的是分层图,同个公司的边是同一层。走的时候你可以在同一层随便乱走,然后可以跑到另外一层的对应点去,这需要1的花费。

所以可以想到如下建边方式:每一层之间的边的边权为0,同一个点的任意两层的点之间边权为1,即表示换乘的花费为1

发现这样建边边数会很多,比如一条边在i层都出现过 那么这个点就要建i(i1)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 @   Starlight_Glimmer  阅读(115)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
历史上的今天:
2019-11-05 换根dp特征总结
2019-11-05 HDU2196 Computer【换根dp】
2019-11-05 CF1187E Tree Painting【换根dp】
2019-11-05 CF-Div.3-B. Minimize the Permutation【模拟·需要清醒的脑子】
2019-11-05 noi.ac-CSP模拟Day5T2 灯
2019-11-05 noi.ac-CSP模拟Day5T1 组【二分图最大匹配】
浏览器标题切换
浏览器标题切换end
点击右上角即可分享
微信分享提示