并查集模板
f数组要初始化
auto find(auto x)
{
if(f[x]==x) return x;
else return f[x]=find(f[x])路径压缩,同一条路上都归到一个点上
}
void unionset(auto a,auto b)
{
f[find(a)]=find(b); auto会自动适配数据类型
}
P3367 【模板】并查集
题目描述
如题,现在有一个并查集,你需要完成合并和查询操作。
输入格式
第一行包含两个整数 N,M ,表示共有 N 个元素和 M 个操作。
接下来 M 行,每行包含三个整数 Zi,Xi,Yi 。
当 Zi=1 时,将 Xi 与 Yi 所在的集合合并。
当 Zi=2 时,输出 Xi 与 Yi 是否在同一集合内,是的输出 Y
;否则输出 N
。
输出格式
对于每一个Zi=2 的操作,都有一行输出,每行包含一个大写字母,为 Y
或者 N
。
输入输出样例
输入
4 7
2 1 2
1 1 2
2 1 2
1 3 4
2 1 4
1 2 3
2 1 4
输出
N
Y
N
Y
思路 :就是并查集模板的套用,首先先给f数组初始化,接着就是对输入的数字判断,看是合并,还是查看是否同组,然后直接调用函数就行了
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
int n,k;
int z,x,y;
int f[10010];
vector<int> vv(10010,1);初始化为1
int find(int x)
{
if(f[x]==x) return x;
return f[x]=find(f[x]);
}
void unity(int x,int y)
{
x=find(x),y=find(y); 按秩合并,直接用模板的也行,用这个的目的是合并的时候下面数字少的
if(x==y) return; 祖先认下面数字多的祖先为祖先,这样查找快点
if(vv[x]>vv[y]) swap(x,y);
f[x]=y;
vv[x]+=vv[y];
}
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++) f[i]=i;数组初始化,即认自己为祖先
while(k--)
{
cin>>z>>x>>y;
if(z==1) unity(x,y);
else
{
x=find(x),y=find(y);
if(x==y) cout<<"Y"<<endl;
else cout<<"N"<<endl;
}
}
return 0;
}
P1656 炸铁路
题目描述
A 国派出将军 uim,对 B 国进行战略性措施,以解救涂炭的生灵。
B 国有 n 个城市,这些城市以铁路相连。任意两个城市都可以通过铁路直接或者间接到达。
uim 发现有些铁路被毁坏之后,某两个城市无法互相通过铁路到达。这样的铁路就被称为 key road。
uim 为了尽快使该国的物流系统瘫痪,希望炸毁铁路,以达到存在某两个城市无法互相通过铁路到达的效果。
然而,只有一发炮弹(A 国国会不给钱了)。所以,他能轰炸哪一条铁路呢?
输入格式
第一行 n,m(1≤n≤150,1≤m≤5000),分别表示有 n 个城市,总共 m 条铁路。
以下 m 行,每行两个整数 a,b,表示城市 a 和城市 b 之间有铁路直接连接。
输出格式
输出有若干行。
每行包含两个数字 a,b,其中a<b,表示 〈a,b〉 是 key road。
请注意:输出时,所有的数对 〈a,b〉 必须按照 a 从小到大排序输出;如果a 相同,则根据 b 从小到大排序。
输入输出样例
输入
6 6
1 2
2 3
2 4
3 5
4 5
5 6
输出
1 2
5 6
输入
10 9
2 1
3 1
4 1
10 4
9 4
6 3
7 3
8 3
5 3
输出
1 2
1 3
1 4
3 5
3 6
3 7
3 8
4 9
4 10
思路:每次从其中拿走一条边,然后就套用并查集的模板,把剩下的边合并,然后就是遍历数组,如果会出现祖先不同的情况,就输出拿走的那一条边
有几点要注意一下,就是要给数据排序,还有a有可能大于b,针对这个要判断一下
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef pair<int,int>PII;
int n,m;
PII q[5010];
int f[160];
bool compare(PII a,PII b)
{
if(a.first==b.first) return a.second<b.second;
return a.first<b.first;
}
int find(int x)
{
if(f[x]==x) return x;
return f[x]=find(f[x]);
}
void unionset(int a,int b)
{
f[find(a)]=find(b);
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>q[i].first>>q[i].second;
if(q[i].first>q[i].second) swap(q[i].first,q[i].second);
}
sort(q+1,q+1+m,compare);
for(int i=1;i<=m;i++)
{
for(int j=1;j<=n;j++) f[j]=j;
for(int j=1;j<=m;j++)
{
if(i!=j) unionset(q[j].first,q[j].second);
}
for(int j=2;j<=n;j++)
{
if(f[find(j)]!=f[find(j-1)])
{
cout<<q[i].first<<" "<<q[i].second<<endl;
break;
}
}
}
return 0;
}
还有一道简单的并查集题目,蓝桥杯的,合根植物,可以看我另一个博客
https://blog.csdn.net/jia_jia_LL/article/details/136978255?spm=1001.2014.3001.5501
标签:输出,int,查集,P1656,include,find,模板 From: https://blog.csdn.net/jia_jia_LL/article/details/137026097