Nothing to fear
种一棵树最好的时间是十年前,其次是现在!
那些你早出晚归付出的刻苦努力,你不想训练,当你觉的太累了但还是要咬牙坚持的时候,那就是在追逐梦想,不要在意终点有什么,要享受路途的过程,或许你不能成就梦想,但一定会有更伟大的事情随之而来。 mamba out~
2020.7.16
人一我十,人十我百,追逐青春的梦想,怀着自信的心,永不言弃!
lg- P1536 - 村村通
并查集本集
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 10010;
int f[N] , vis[N];
int n , m;
int find(int k)
{
if(k == f[k])return k;
else return f[k] = find(f[k]);
}
void Union(int a,int b)
{
vis[a] = vis[b] = 1;
int A = find(a) , B = find(b);
f[A] = B;
}
void init()
{
for(int i = 0;i < N ;i++)f[i] = i;
memset(vis , 0 ,sizeof vis);
}
int main()
{
while(1)
{
cin >> n;
if(n == 0)break;
cin >> m;init();
int a , b , cnt = 0;
for(int i = 0;i < m;i ++)
{
scanf("%d %d",&a , &b);
Union(a , b);
}
for(int i = 1;i <= n;i ++){
if(find(i) == i)cnt++;
}
cout << cnt - 1 << endl;
}
return 0;
}
lg - P1892 [BOI2003]团伙
分析
既然连个人互为朋友那么必然可以属于一个团体之中,故此时需要合并,
如果两个人互为敌人那么此时由于敌人的敌人依旧是我们的朋友我们可以遍历敌人的敌人,将其当作朋友进行合并,整个过程由并查集 + 链式前向星完成。并查集负责集合查找,链式前向星负责存储每个人的敌人
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
const int N = 1005;
int f[N] , vis[N] , n , m;
struct edge{
int w , to ,next;
}e[N * N];
int head[N] , tot;
int find(int k)
{
if(k == f[k])return k;
else return f[k] = find(f[k]);
}
void Union(int a,int b)
{
int A = find(a) , B = find(b);
f[A] = B;
}
void add(int a,int b)
{
e[++tot].to = b;
e[tot].next = head[a];
head[a] = tot;
}
int main()
{
cin >> n >> m;
for(int i = 1;i <= n;i ++)f[i] = i;
char ch;int a , b;
for(int i = 0;i < m;i ++)
{
cin >> ch >> a >> b;
if(ch == 'F')Union(a , b);
else{
add(a , b) , add(b , a);
// 寻找 b 的敌人作为a的朋友
for(int j = head[b] ; j ;j = e[j].next)
{
int y = e[j].to;
Union(a , y);
}
// 寻找 a 的敌人作为 b 的朋友
for(int j = head[a] ; j ;j = e[j].next)
{
int y = e[j].to;
Union(b , y);
}
}
}
int ans = 0;
for(int i = 1;i <= n;i ++)
{
if(i == find(i))ans++;
}
cout << ans << endl;
return 0;
}