首页 > 其他分享 >[Rudolf and Subway]

[Rudolf and Subway]

时间:2024-04-05 17:46:34浏览次数:15  
标签:cnt const int edge Subway 图层 include Rudolf

Rudolf and Subway

题目大意

给定一个\(n\)个点,\(m\)条边的无向图,第\(i\)条边表示\(x,y\)是\(z\)号线的相邻站点,问\(s\)到\(t\)最少需要换乘多少次

做法

用分层图,对于任意一条线路,让他们单独分为一层,如果一个点既在\(1\)号线又在\(2\)号线,那么它应该处于两个图层中,举个例子

4 4
1 2 1
1 3 2
4 3 1
2 3 1

在这个例子中显然\(1,2,3,4\)可以在一个图层中,同时\(1,3\)又可以在第二个图层中,分层的目的是为了,如果它需要去另一个图层,说明他一定要换乘(当前节点跳到另一个图层的当前节点不算),那么可以多创造一些'分身',来表示多个图层中都包含某个点,建边不按原来的建,而是首先要自己向自己的所有分身去建边保证可以由这个点换乘到其他图层中去,然后每个图层之间点,按照原来的关系去建边,然后令自己到分身长度为0,图层之间建边长度为0,由分身到本体的长度为1,最后跑最短路即可。

#include <map>
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
typedef long long LL;
using namespace std;
const int maxn = 2e5+6,inf = 1e9;
int T,n,m,cnt,head[maxn*3],dis[maxn*3];
bool vis[maxn*3];
struct qwq{
	int to,len,next;
}edge[maxn*6];
struct node{
	int id,dist;
	bool operator < (const node &x)const
	{
		return dist > x.dist;
	}
};
priority_queue <node> q;
struct p{
	int fi,se;
	bool operator < (const p &x)const
	{
		return fi == x.fi ? se < x.se : fi < x.fi;
	}
};
map <p,int> mp;

inline void add(int u,int v,int w)
{
	cnt ++;
	edge[cnt].to = v;
	edge[cnt].len = w;
	edge[cnt].next = head[u];
	head[u] = cnt;
	return ;
}

int main()
{
	scanf("%d",&T);
	while(T --)
	{
		cnt = 0; mp.clear();
		scanf("%d%d",&n,&m);//n 2e5 m 2e5
		for(int i=1;i<=m;i++)
		{
	        int x,y,z,nx,ny;
	        scanf("%d%d%d",&x,&y,&z);
	        if(!mp[{x,z}])
			{
	            mp[{x,z}] = ++n;
	            nx = n;
	            add(nx,x,1);
	            add(x,nx,0);
	        }
			else nx = mp[{x,z}];
	        if(!mp[{y,z}])
			{
	            mp[{y,z}] = ++n;
	            ny = n;
	            add(ny,y,1);
	            add(y,ny,0);
	        }
			else ny = mp[{y,z}];
	        add(nx,ny,0);
	        add(ny,nx,0);
	    }
	    //n + m * 2 = 6e5
	    //cnt : 6 * m = 12e5
		for(int i=1;i<=n;i++)
		{
			dis[i] = inf;
			vis[i] = 0;
		}
		int b,e;
		scanf("%d%d",&b,&e);
		dis[b] = 0;
		q.push((node){b,0});
		while (!q.empty())
		{
	        int u = q.top().id; q.pop();
	        if(vis[u]) continue;
	        vis[u] = 1;
	        for(int i=head[u];i;i=edge[i].next)
	        {
	        	int v = edge[i].to;
	        	if(dis[v] > dis[u] + edge[i].len)
	        	{
	        		dis[v] = dis[u] + edge[i].len;
	        		q.push((node){v,dis[v]});
				}
			}
	    }
		for(int i=1;i<=n;i++) head[i] = 0; 
		printf("%d\n",dis[e]);
	}
	return 0;
}
/*
1
4 4
1 2 43
1 3 34
4 3 43
2 3 43
1 1
*/

标签:cnt,const,int,edge,Subway,图层,include,Rudolf
From: https://www.cnblogs.com/-Wind-/p/18115941

相关文章

  • CF371E Subway Innovation 题解
    题目链接:CF或者洛谷对于绝对值的几何意义来说,这题是在直线上的两点间的距离,为了总的距离和最下,首先最好让它们两两之间最好都紧挨着。由于询问的是\((i,j)\)不重不漏的对有关,即\((i<j)\+\(i>j)\+\(i=j)=all(i,j)\),又因为,\((i,j)\)的贡献和\((j,i)\)相同且重复,所以我......
  • 题解:CF1941G Rudolf and Subway
    原题链接简化题意一个无向连通图中将边分成了不同颜色(保证同种颜色联通),问从\(b\)到\(e\)最短需要经过几种颜色思路考虑因为同种颜色联通,可直接在读入的时候开两个vector分别存每个点属于的颜色及每种颜色有哪些点,又因为颜色数字可能跨度比较大,最好另开一个存颜色的种......
  • D. Rudolf and the Ball Game
    题解:模拟+去重每一次扔球都将所有可能性加入队列,并设为一层;然后将一层的可能性挨个出列并进行 ((qj+ri−1) mod n+1),((qj−ri−1+n) mod n+1)操作,然后去重后入列。code #include<bits/stdc++.h>usingnamespacestd;constintN=2e5+5;inta[N],b[1005];intmain()......
  • Codeforces Round 933 G. Rudolf and Subway
    原题链接:Problem-G-Codeforces思路:根据题意可知相同颜色的边一定是联通的,那么就可以设置虚点,例如1-2,2-3,3-4边的颜色都是相同的,那么就可以设置一个特殊的点例如设置为10,那么这三条边就可以改成1-10,10-2,2-10,10-3,3-10,10-4,从点到虚点需要1的代价,但是从虚点到其他点不需要代价,......
  • Codeforces Round 933 Rudolf and k Bridges
    原题链接:Problem-E-Codeforces题目大意:给一个行为n列为m的河流二维数组,数字代表河流的深度。题目要求连续建造k座桥,桥的定义是从第一列到第m列,每隔d需要按照支架,安装支架的代价是深度+1。问安装最少需要多少代价?思路:单调队列优化dp,dp数组只需要一维,dp[i]的含义是从1到i建......
  • B. Rudolf and 121
    题解由于a1的值只能通过对a2的操作进行消除,所以我们可以先根据a1的值迭代出a2,a3的值,然后此时的a2,只能通过a3的操作进行消除.....以此类推,如果其中发现有ai的值<0就输出NO。code #include<bits/stdc++.h>usingnamespacestd;constintN=2e5+5;inta[N];intmain(){//......
  • C. Rudolf and the Ugly String
    题解遇到map时,sum++;遇到pie时,sum++。特殊情况遇到mapie时,sum--(因为map,pie分别加了一次,但是该子串只需要去掉p即可)code #include<bits/stdc++.h>usingnamespacestd;constintN=2e5+5;inta[N];intmain(){//freopen("input.txt","r",stdin);intt;ci......
  • A. Rudolf and the Ticket
    题解简单的二分应用,对于每个bi我们只需找到最大的ci使得bi+ci<=target即可code #include<bits/stdc++.h>usingnamespacestd;inta[105],b[105];intmain(){//freopen("input.txt","r",stdin);intt;cin>>t;while(t--){int......
  • G. Rudolf and Subway
    原题链接题解太巧妙了!!原题等效于该分层图,然后广搜本题中我用了另一种方法建边,因为清空太麻烦了code#include<bits/stdc++.h>usingnamespacestd;intmain(){ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);intt;cin>>t;while(t--)......
  • F. Rudolf and Imbalance
    原题链接题解最大值最小\(\to\)二分可行性判断:二分间断值\(len\\to\)如果原序列\(a_i-a_{i-1}>len\)\(\to\)双指针判断有没有\(b+f\)使得\(a_i-len<=b+f<=a_{i-1}+len\)由于只能使用一次,所以若使用两次也算错code#include<bits/stdc++.h>usingnamespacestd;......