“美登杯”上海市高校大学生程序设计邀请赛 (华东理工大学)C题 小花梨判连通
思路:
1.对于每个图用并查集对每个联通块染***r> 2.k次染色可以的得出每个点(1~n)的染色序列
3.如果i j两个点联通那么他们的染色序列相同,所以map所有染色序列即可
这里对序列排序使用的是自定义字典序排序,需要往map第三个参数传入一个类函数模板(不能是函数指针)
/*
思路:
1.对于每个图用并查集对每个联通块染色
2.k次染色可以的得出每个点(1~n)的染色序列
3.如果i j两个点联通那么他们的染色序列相同,所以map所有染色序列即可
*/
#include<bits/stdc++.h>
#define mset(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
int father[100005];
int n,k;
void init()
{
for(int i=1; i<=n; ++i) father[i]=i;
}
int Find(int x)
{
if(x==father[x]) return x;
return father[x]=Find(father[x]);
}
class cmp{
public:
bool operator()(vector<int> aa,vector<int> bb)
{
for(int i=0; i<k; ++i)
if(aa[i]!=bb[i]) return aa[i]<bb[i];
return false;//相等时候一定要返回false,想一下两个数之间判断是否相等的原理就知道了
}
};
vector<int> seq[100005];
map< vector<int>,int,cmp> mmp;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>k;
for(int pp=0; pp<k; ++pp)
{
int m;
cin>>m;
init();
for(int i=1; i<=m; ++i)
{
int u,v,fu,fv;
cin>>u>>v;
fu=Find(u);
fv=Find(v);
father[fu]=fv;
}
for(int i=1; i<=n; ++i)
{
int bb=Find(i);
seq[i].push_back(bb);
}
}
for(int i=1;i<=n;++i)
mmp[seq[i]]+=1;
for(int i=1;i<=n;++i)
cout<<mmp[seq[i]]<<endl;
return 0;
}