首先要熟练并查集基本模板:
1 #include <stdio.h>
2
3 const int MAXN = 100; /*结点数目上线*/
4 int pa[MAXN]; /*p[x]表示x的父节点*/
5 int rank[MAXN]; /*rank[x]是x的高度的一个上界*/
6
7 void make_set(int x)
8 {/*创建一个单元集*/
9 pa[x] = x;
10 rank[x] = 0;
11 }
12
13 int find_set(int x)
14 {/*带路径压缩的查找*/
15 if(x != pa[x])
16 pa[x] = find_set(p[x]);
17 return pa[x];
18 }
19
20 /*按秩合并x,y所在的集合*/
21 void union_set(int x, int y)
22 {
23 x = find_set(x);
24 y = find_set(y);
25 if(rank[x] > rank[y])/*让rank比较高的作为父结点*/
26 pa[y] = x;
27 else
28 {
29 pa[x] = y;
30 if(rank[x] == rank[y])
31 rank[y]++;
32 }
33 }
例题:POJ 1611
哟呵呵,果然自己打一遍还是出现了问题,在哪里呢,就是在初始化的地方啊!!!!!
并查集一个很重要的地方就是初始化
fa[i]=i;rank[i]=0; //啦啦啦啦啦啦,啦啦啦啦啦
2014.11.26
最近一直在看并查集,感觉小有收获,嘿嘿~
并查集要分析好,代码不是很长
注意在合并的时候要做更新
在求最小生成树的时候kruskal和并查集是很好的结合
code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
#define N 105
#define INF 0xfffffff
using namespace std;
int f[N];
typedef struct
{
int x,y,len;
}Edge;
Edge edge[N];
int find(int x)
{
return f[x]=f[x]==x?x:find(f[x]);
}
int cmp(const void *a,const void *b)
{
return ((Edge *)a)->len>((Edge *)b)->len?1:-1;
}
int n,m;
int kruskal(int o) //here.the kruskal is not as difficult as i thought.oh yeah!
{
int cnt=0;
for(int i=1;i<=n;i++) f[i]=i;
for(int i=o;i<m;i++)
{
int f1=find(f[edge[o].x]);
int f2=find(f[edge[o].y]);
{
f[f1]=f2;
cnt++;
}
if(cnt==n-1) return edge[i].len-edge[o].len;
}
return INF;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0) break;
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].len);
}
qsort(edge,m,sizeof(edge[0]),cmp);
int ans=INF;
for(int i=0;i<=m-n+1;i++)
{
int k=kruskal(i);
if(k<ans) ans=k;
}
if(ans==INF) puts("-1");
else printf("%d\n",ans);
}
}
find them catch them:
#include<cstdio>
#include<cstring>
#define N 100000+10
int f[N],c[N];
int n,m;
int find(int x)
{
if(f[x]==x) return x;
int t=f[x];
f[x]=find(f[x]);
c[x]=(c[x]+c[t])%2; //解题关键
return f[x];
}
void make(char s,int x,int y)
{
int f1=find(x);
int f2=find(y);
if(f1!=f2)
{
if(s=='A')
{printf("Not sure yet.\n");return;}
f[f1]=f2;
if((c[x]+c[y])%2==0)
c[f1]=1;//这里错了!!!好好思考一下
}
else
{
if(s=='A')
{
if(c[x]==c[y]) printf("In the same gang.\n");
else printf("In different gangs.\n");
return;
}
return;
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++) f[i]=i;
memset(c,0,sizeof(c));
for(int i=0;i<m;i++)
{
char s[5];
int a,b;
scanf("%s",s);
scanf("%d%d",&a,&b);
make(s[0],a,b);
}
}
}
/*
20
20 20
D 2 5
D 3 5
D 1 4
D 1 2
A 4 1
*/