交题网址:
① 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;
}