Mr. Kitayuta‘s Colorful Graph CodeForces - 505B(好题,连通性判断,两种方法:floyd/并查集)

题意:一个无向图包含 n 个点 m 条边,顶点编号从 1 n 。连接着顶点 ai 和顶点 bi的边的颜色为 ci 。之后有 q 个询问。每条询问有两个整数 uivi,找到满足下面条件的颜色个数:同一种颜色的路径连接顶点 ui 和顶点 vi

题解:本题显然是让判断颜色的联通性,关于连通性的判断我们可以用并查集实现,只不过这里的并查集多了一个颜色属性,我们需要在并查集再开一维颜色属性。此外,本题其实是连通性的传递,涉及传递闭包且数据较小,所以可以直接使用floyd实现连通性的传递。

并查集AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
const int maxn=105;
int n,m,f[maxn][maxn];
int find_x(int x,int c) {
	if(f[x][c]!=x) return f[x][c]=find_x(f[x][c],c);
	else return x;
}
void unite(int x,int y,int c) {
	int aa=find_x(x,c);
	int bb=find_x(y,c);
	if(aa!=bb)f[aa][c]=bb;
}
main() {
	IOS;
	int n,m;
	cin>>n>>m;
	for(int i=1; i<=n; i++)
		for(int j=1; j<=m; j++)
			f[i][j]=i;
	for(int i=1; i<=m; i++) {
		int x,y,w;
		cin>>x>>y>>w;
		unite(x,y,w);
	}
	int t;
	cin>>t;
	while(t--){
		int x,y,ans=0;
		cin>>x>>y;
		for(int i=1;i<=m;i++){
			int aa=find_x(x,i);
			int bb=find_x(y,i);
			if(aa==bb)ans++;
		}
		cout<<ans<<endl;
	}
}

Floyd_AC代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
int n,m,d[105][105][105];
void floyd() {
	for(int k=1; k<=n; k++)//floyd的中间结点层枚举时一定要放在第一层 
		for(int i=1; i<=n; i++)
			for(int j=1; j<=n; j++)
				//for(int k=1; k<=n; k++)
				for(int c=1; c<=m; c++)
					if(d[i][k][c]&&d[j][k][c])d[i][j][c]=1;
}
main() {
	IOS;
	cin>>n>>m;
	for(int i=1; i<=m; i++) {
		int x,y,w;
		cin>>x>>y>>w;
		d[x][y][w]=1;
		d[y][x][w]=1;
	}
	floyd();
	int t;
	cin>>t;
	while(t--) {
		int x,y,ans=0;
		cin>>x>>y;
		for(int i=1; i<=m; i++) {
			if(d[x][y][i])ans++;
		}
		cout<<ans<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/Alanrookie/article/details/107779326