题解:CF1941G Rudolf and Subway

原题链接

简化题意

一个无向连通图中将边分成了不同颜色(保证同种颜色联通),问从 \(b\)\(e\) 最短需要经过几种颜色

思路

考虑因为同种颜色联通,可直接在读入的时候开两个 vector 分别存每个点属于的颜色及每种颜色有哪些点,又因为颜色数字可能跨度比较大,最好另开一个存颜色的种类

然后就是从 \(b\) 开始 BFS ,对每个点遍历它直连的所有颜色种类,然后遍历属于该颜色的所有点

小优化

发现存颜色的时候会将一条边连着的两个点都存进去,存点同理,也就是一个点可能会被同颜色存很多次且可能存很多个同颜色,这里开两个 map 去重可以大大降低复杂度

注意!!!

因为 codeforces 上可以 hack 别人的代码,所以赛后数据有卡 hash 表的,建议观看 这篇
CF 大佬的博客,防止自己的 hash 表被卡

开两个数组存遍历过的颜色块和节点,复杂度显然是线性的

代码

#include<bits/stdc++.h>
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#define ll long long
using namespace std;
//using namespace __gnu_cxx;
//using namespace __gnu_pbds;

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        // http://xorshift.di.unimi.it/splitmix64.c
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

const int N=4e5+10;
int T,n,m,b,e,ans;
bool fc[N],fl[N],fd[N];
queue<pair<int,int>>q;
vector<int>col[N],v[N],vec;
unordered_map<int,bool,custom_hash>mp1;
unordered_map<long long,bool,custom_hash>mp2;
inline void init()
{
	while(!q.empty())
		q.pop();
	for(auto it : col[e])
		fl[it]=false;
	for(int i=1;i<=n;i++)
	{
		fd[i]=false;
		col[i].clear();
	}
	for(auto it : vec)
	{
		fc[it]=false;
		v[it].clear();
	}
	ans=1e9;
	vec.clear();
	mp1.clear();
	mp2.clear();
	return ;
}
inline void bfs(int x,int t)
{
	fd[x]=true;
	q.push({x,t});
	while(!q.empty())
	{
		x=q.front().first;
		t=q.front().second;
		q.pop();
		for(auto i : col[x])
		{
			if(fc[i])
				continue;
			if(fl[i])
			{
				ans=min(ans,t);
				return ;
			}
			fc[i]=true;
			for(auto j : v[i])
				if(!fd[j])
				{
					fd[j]=true;
					q.push({j,t+1});
				}
		}
	}
	return ;
}
int main()
{
	cin>>T;
	while(T--)
	{
		init();
		scanf("%d%d",&n,&m);
		for(int i=1,x,y,c;i<=m;i++)
		{
			scanf("%d%d%d",&x,&y,&c);
			if(mp1.find(c)==mp1.end())
			{
				mp1[c]=1;
				vec.push_back(c);
			}
			if(mp2.find(((ll)x<<32)|c)==mp2.end())
			{
				mp2[((ll)x<<32)|c]=1;
				v[c].push_back(x);
				col[x].push_back(c);
			}
			if(mp2.find(((ll)y<<32)|c)==mp2.end())
			{
				mp2[((ll)y<<32)|c]=1;
				v[c].push_back(y);
				col[y].push_back(c);
			}
		}
		scanf("%d%d",&b,&e);
		if(b==e)
		{
			printf("0\n");
			continue;
		}
		for(auto it : col[e])
			fl[it]=true;
		bfs(b,1);
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2024-03-19 10:43  lxyt-415x  阅读(57)  评论(0编辑  收藏  举报