假期训练正式开始了, 然而我还是在补题。。。。
A:点击打开链接
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 30000 + 5;
int par[maxn];
int rank_[maxn];
int under[maxn];
void init()
{
for(int i = 0; i < maxn; ++i)
{
par[i] = i;
rank_[i] = 1;
under[i] = 0;
}
}
int find_(int x)
{
if(par[x] == x) return x;
int temp = par[x];
par[x] = find_(par[x]);
under[x] += under[temp];
return par[x];
}
void unite(int x, int y)
{
x = find_(x);
y = find_(y);
if(x == y) return;
else
{
par[x] = y;
under[x] = rank_[y];
rank_[y] += rank_[x];
}
}
int main()
{
int N;
while(cin >> N)
{
getchar();
init();
while(N--)
{
char s[3];
scanf("%s", s);
if(s[0] == 'M')
{
int x, y;
scanf("%d%d", &x, &y);
unite(x, y);
}
else if(s[0] == 'C')
{
int x;
scanf("%d", &x);
find_(x);
printf("%d\n", under[x]);
}
}
}
return 0;
}
B:
点击打开链接
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 10000 + 5;
int par[maxn];
int rank_[maxn];
int kk[11][4] = { {1,1,0,0} , {0,1,1,0} , {1,0,0,1} , {0,0,1,1} , {0,1,0,1} ,
{1,0,1,0} , {1,1,1,0} , {1,1,0,1} , {1,0,1,1} , {0,1,1,1} , {1,1,1,1} };
void init()
{
for(int i = 0; i < maxn; ++i)
{
par[i] = i;
rank_[i] = 0;
}
}
int find_(int x)
{
if(par[x] == x)
return x;
else
return par[x] = find_(par[x]);
}
void unite(int x, int y)
{
x = find_(x);
y = find_(y);
if(x == y) return;
if(rank_[x] < rank_[y])
par[x] = y;
else
{
par[y] = x;
if(rank_[x] == rank_[y]) rank_[x]++;
}
}
int main()
{
int n, m;
while(scanf("%d%d", &n, &m) != EOF)
{
if(n==-1 && m==-1) break;
init();
char vis[50 + 5][50 + 5];
for(int i = 0; i < n; ++i)
scanf("%s", vis[i]);
for(int i = 0; i < n; ++i)
{
for(int j = 0; j < m; ++j)
{
if(j>0 && kk[vis[i][j] - 'A'][0] == 1 && kk[vis[i][j-1] - 'A'][2] == 1)
unite(i*m+j, i*m + j-1);
if(i>0 && kk[vis[i][j] - 'A'][1] == 1 && kk[vis[i-1][j] - 'A'][3] == 1)
unite(i*m+j, (i-1)*m + j);
}
}
int cnt = 0;
for(int i = 0; i < n*m; ++i)
{
if(par[i] == i) ++cnt;
}
cout << cnt << endl;
}
}
C:
点击打开链接
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1000 + 5;
int par[maxn];
int rank_[maxn];
void init()
{
for(int i = 0; i < maxn; ++i)
{
par[i] = i;
rank_[i] = 0;
}
}
int find_(int x)
{
if(par[x] == x)
return x;
else
return par[x] = find_(par[x]);
}
void unite(int x, int y)
{
x = find_(x);
y = find_(y);
if(x == y) return;
if(rank_[x] < rank_[y])
par[x] = y;
else
{
par[y] = x;
if(rank_[x] == rank_[y]) rank_[x]++;
}
}
int main()
{
int N, M;
while(cin >> N && N)
{
cin >> M;
init();
for(int i = 0; i < M; ++i)
{
int x, y;
scanf("%d%d", &x, &y);
unite(x, y);
}
int cnt = 0;
for(int i = 1; i <= N; ++i)
{
if(find_(i) == i)
++cnt;
}
cout << cnt - 1 << endl;
}
}
D:
点击打开链接
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 100000;
bool ans[maxn];
int _rank[maxn];
int _par[maxn];
void INIT()
{
for(int i = 1; i < maxn; ++i) _rank[i] = 0;
for(int i = 1; i < maxn; ++i) _par[i] = i;
}
int _Find(int x)
{
return _par[x] == x ? _par[x] : _par[x] = _Find(_par[x]);
}
void Unite(int x, int y)
{
x = _Find(x); y = _Find(y);
if(x==y) return ;
if(_rank[x] < _rank[y]) _par[x] = y;
else
{
_par[y] = x;
if(_rank[x] == _rank[y]) _rank[x]++;
}
}
int main()
{
int x,y;
while(scanf("%d%d", &x, &y) == 2)
{
if(x==0&&y==0) cout << "Yes" << endl;
if(x==-1 && y==-1) break;
INIT();
ans[x] = ans[y] = 1;
Unite(x,y);
bool ok = true;
while(scanf("%d%d", &x, &y) == 2)
{
if(x==0 && y==0) break;
ans[x] = ans[y] = 1;
x = _Find(x); y = _Find(y);
Unite(x,y);
if(x==y) ok = false;
}
int cnt = 0;
for(int i = 1; i < maxn; ++i)
{
if(ans[i] && _par[i] == i) ++cnt;
if(cnt>1) {ok = false; break;}
}
if(ok) cout << "Yes" << endl;
else cout << "No" << endl;
memset(ans,0,sizeof(ans));
}
return 0;
}
E:
点击打开链接
#include<iostream>
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1e5 + 5;
int par[maxn];
int vis[maxn];
int main()
{
int x,y;
int kase = 0;
while(1)
{
int sum = 0;
int cnt = 0;
bool ok = true;
memset(par,0,sizeof(par));
memset(vis,0,sizeof(vis));
int n = 0;
for(n = 0; ; ++n)
{
scanf("%d%d", &x, &y);
if(x < 0 && y < 0) return 0;
if(x==0 && y==0) break;
if(!vis[x]) ++cnt, ++sum, vis[x] = 1;
if(!vis[y]) ++sum, vis[y] = 1;
else --cnt;
if(par[y] != 0) ok = false;
par[y] = x;
}
if(n != 0 && n != sum-1) ok = false;
if(n != 0 && cnt != 1) ok = false;
if(ok) printf("Case %d is a tree.\n", ++kase);
else printf("Case %d is not a tree.\n", ++kase);
}
return 0;
}
F:
点击打开链接
#include<iostream>
#include<cstdio>
#include<set>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 2000000 + 5;
int par[maxn];
int kk[maxn];
void init()
{
for(int i = 0; i < maxn; ++i)
{
par[i] = i;
kk[i] = i;
}
}
int find_(int x)
{
if(par[x] == x)
return x;
else
return par[x] = find_(par[x]);
}
void unite(int x, int y)
{
x = find_(x);
y = find_(y);
if(x != y)
par[x] = y;
}
int main()
{
int n, m;
int kase = 0;
while (cin >> n >> m)
{
if(n==0 && m==0) return 0;
init();
int cnt = n;
while(m--)
{
char s[3];
scanf("%s", s);
if (s[0] == 'M')
{
int x, y;
scanf("%d%d", &x, &y);
unite(kk[x], kk[y]);
}
else if(s[0] == 'S')
{
int x;
scanf("%d", &x);
kk[x] = cnt;
par[cnt] = cnt;
++cnt;
}
}
set <int> vis;
for (int i = 0; i < n; i++)
vis.insert(find_(kk[i]));
printf("Case #%d: %d\n", ++kase, vis.size());
}
return 0;
}
并查集本身没有啥难的, 主要是它的变形应用