【蓝桥】【CS505B】Mr. Kitayuta's Colorful Graph(并查集)

交题网址:

http://codeforces.com/problemset/problem/505/B
https://cn.vjudge.net/problem/CodeForces-505B

题目描述

一个无向图包含n个点m条边,顶点编号从1到n。 对于每条边有颜色ci, 连接着顶点 ai 和 b i.
下面有q个询问.
每条询问有两个整数 — ui 和 vi.
找到满足下面条件的颜色个数: 同一种颜色的路径连接顶点 ui 和 顶点 vi

输入描述

第一行是两个整数 — n and m (2 ≤ n ≤ 100, 1 ≤ m ≤ 100), 代表着定点个数和边的个数
接下来m行有三个整数 — ai, bi (1 ≤ ai < bi ≤ n) and ci (1 ≤ ci ≤ m).
下一行有一个整数 — q (1 ≤ q ≤ 100), 代表询问次数
接下来q行,每行两个整数 — ui 和 vi (1 ≤ ui, vi ≤ n). 默认 ui ≠ vi.

输出描述

对于每次询问,在单独的一行输出答案

例如

节点1和节点2被 1,2颜色连接
节点3和节点4被 3颜色连接
节点1和节点4不被任何颜色连接
(图见末尾)

样例

Input
4 5
1 2 1
1 2 2
2 3 1
2 3 3
2 4 3
3
1 2
3 4
1 4
Output
2
1
0

思路

多组并查集,就酱d=====( ̄▽ ̄*)b

代码1

由于会的东西不多,能不能拿好的奖很多时候只能靠运气
这题基本掌握并查集做出来可说是轻松加愉快了
不要用cin,cout,不要问我怎么知道的

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e2+1;
int pre[maxn][maxn];  //前者表示颜色,后者表示当前结点的BOSS结点

int find(int root,int color)
{
	int son,tmp;
	son=root;
	while(root!=pre[color][root])
		root=pre[color][root];
	while(son != root) {
		tmp=pre[color][son];
		pre[color][son]=root;
		son=tmp;
	}
	return root;

}
int main()
{
	int n,m,start,end,color;
	int root1,root2;
	scanf("%d %d",&n,&m) ;
	int len = m,mxn=0;
	memset(pre,0,sizeof(pre));
	for(int i=1; i<=m; i++)  //m种颜色
		for(int j=1; j<=n; j++) //n个结点
			pre[i][j]=j;

	while(len--) {
		//cin>>start>>end>>color;
		scanf("%d %d %d",&start,&end,&color);
		if(color>mxn) mxn=color;
		root1=find(start,color);
		root2=find(end,color);
		if(root1!=root2) {
			pre[color][root1]=root2;
		}
	}

	int q;
	//cin>>q;
	scanf("%d",&q);
	while(q--) {
		int s,e,i,cnt=0;
		//cin>>s>>e;
		scanf("%d %d ",&s,&e); 
		for(i=1; i<=mxn; i++) {
			if(find(s,i)==find(e,i)) {
				cnt++;
			}
		}
		//cout<<cnt<<endl;
		printf("%d\n",cnt);
	}

	return 0;
}

代码2

上面代码的稍微优化(简略)版
最近登codeforces是真的卡呀(ノへ ̄、)

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e2+10;
//根据颜色不同确定不同的并查集BOSS结点
//前者颜色后者当前结点BOSS结点
int pre[maxn][maxn];
int n,m,len;//n个结点,m条边 ,len=m
int a,b,c;//a->b,颜色c
int find(int c,int root)//寻找BOSS结点
{
	while(pre[c][root]!=root)
		root=pre[c][root];
	return root;
}
void init()
{
	scanf("%d %d",&n,&m);
	for(int i=1; i<=m; i++) //颜色
		for(int j=1; j<=n; j++) //顶点数
			pre[i][j]=j; //初始情况下,所有结点的BOSS结点为其自身
	len=m;
	while(len--) {
		scanf("%d %d %d",&a,&b,&c);
		int root1=find(c,a),root2=find(c,b);
		if(root1!=root2) pre[c][root1]=root2;
	}
}
int main()
{
	init();
	scanf("%d",&len);//询问的次数
	while(len--) {
		int ans=0;
		scanf("%d %d",&a,&b);
		for(int i=1; i<=m; i++)
			if(find(i,a)==find(i,b))
				ans++;
		printf("%d\n",ans);
	}
	return 0;
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值