小学期训练题B-并查集
2015-07-25 09:15
351 查看
假期训练正式开始了, 然而我还是在补题。。。。
A:点击打开链接
并查集本身没有啥难的, 主要是它的变形应用
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; }
并查集本身没有啥难的, 主要是它的变形应用
相关文章推荐
- Visual Studio 2013 Xamarin for iOS 环境搭建
- 欢迎页面welcome.jsp
- Navicat通过SSH 设置连接数据库
- poj2409 Let it Bead
- HDOJ 1094 A+B for Input-Output Practice (VI)(水题)
- sdut 3262 Circle of Friends (SCC缩点)
- 【转】C#中对IDisposable接口的理解
- 固定表头带滚动条的HTML表格
- [LeetCode]Sort List
- HDU5296从一棵树上取出若干不连通的点
- 程序员,为什么千万不要重写代码?
- eclipse中配置maven
- sphinx 命令
- eclipse中配置maven
- CentOS 安装 Nginx
- web服务启动spring自动执行ApplicationListener的用法
- 欧拉函数 求小于某个数并与其互质的数的个数
- readline( )库的安装和使用,实现命令补全
- arduino 串口命令解析
- 北京航空航天大学计算机系考研复试上机真题及答案---2014