·并查集:
并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问
easy girl,easy come on QAQ
int find(int x)
{
if(fa[x]==x) return x;
return find(fa[x]);
}
对于不相交集合的操作,一般采用两种启发式优化的方法:
1. 按秩合并:使包含较少结点的树根指向包含较多结点的树根。
2. 路径压缩:使路径查找上的每个点都直接指向根结点
平时用路径压缩就ok,能解决很多东西√
int find(int x)
{
if(fa[x]==x) return x;
return find(fa[x]);
}
void Union(int x, int y)
{
x=find(x),y=find(y);
if(x!=y)
{
if(rank[x]>rank[y]) fa[y]=x;
else
{
fa[x]=y;
if(rank[x]==rank[y])
rank[y]++;
}
}
}
int find(int x)
{
if(x!=fa[x]) fa[x]=find(fa[x]);
return fa[x];
}
int find__(int x)
{
int fx=x;
while(fa[x]!=fx) fx=fa[x];
while(fx!=x)
{
int rt=fa[x];
fa[x]=fx;
x=rt;
}
return x;
}
·带权并查集:
是指在并查集中加入了一个dist[ ]数组;
数组可以记录很多种东西,不一定是类似距离这种东西,也可以是相对于根节点的状态;
emmmm我写的比较简陋↓↓↓
int find_(int x)
{
if(fa[x]==x) return x;
int root=find(fa[x]);
dist[x]+=dist[fa[x]];
return fa[x]=root;
}
至于具体的再根据题目调整啦
·类型题
洛谷p2024食物链[模板题]
又把题翻出来重写了一遍……以前写的太丑了……
虽然现在也没好到哪里去,依旧写得很累赘QAQ,代码风格极骚
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int maxn=100000+5;
int n,k;
int ans=0;
int fa[maxn];
int dist[maxn];
int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
void init(int n)
{
for(int i=0;i<=n;i++)
{
fa[i]=i;
dist[i]=0;
}
}
int find_(int x)
{
if(fa[x]==x) return x;
int root=find_(fa[x]);
dist[x]=(dist[x]+dist[fa[x]])%3;
return fa[x]=root;
}
void Union(int v,int x,int y)
{
int fx=find_(x);
int fy=find_(y);
if(fx!=fy)
{
fa[fx]=fy;
dist[fx]=(v+dist[y]-dist[x]+3)%3;
}
}
int main()
{
n=read(),k=read();
init(n);
ans=0;
for(int i=1;i<=k;i++)
{
int a=read(),b=read(),c=read();
a--;
if(b>n || c>n)
{
ans++;
continue;
}
if(a==1 && b==c)
{
ans++;
continue;
}
int fx=find_(b);
int fy=find_(c);
if(fx!=fy) Union(a,b,c);
else
{
if((dist[b]-dist[c]+3)%3!=a) ans++;
}
}
cout<
poj2492 A Bug‘s life (虫虫总动员?QAQ开玩笑的啦)
题意:
给出T组数据,每组数据表示有n只虫和m对关系,接下来m行输入(x,y),表示x和y是相爱的异性,若这m对关系中出现了错误,即后给出的关系与之前的关系互相冲突(同性相爱),则输出“Suspicious bugs found!”,否则输出“No suspicious bugs found!”
关系并查集,带权的第二类;
用rank[i]来表示i与根节点的关系,rank[]=1表示同性,rank[]=0表示异性;
以下,供上调了很久WA无数次,最后发现是输出大小写错误的代码QAQ↓↓↓
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define LL long long
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int maxn=2000+10;
int n,m;
bool flag=0;
int fa[maxn];
int rank[maxn];
int read()
{
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
void init()
{
for(int i=0;i<=maxn;i++)
{
fa[i]=i;
rank[i]=1;
}
flag=0;
}
int find(int x)
{
if(fa[x]==x) return x;
int root=find(fa[x]);
rank[x]=(rank[x]+rank[fa[x]]+1)&1;
return fa[x]=root;
}
void Union(int x,int y)
{
int fx=find(x);
int fy=find(y);
if(fx!=fy)
{
fa[fx]=fy;
rank[fx]=(rank[x]+rank[y])&1;
}
else
{
if(!((rank[x]+rank[y])&1)) flag=1;
}
}
int main()
{
int Case=0;
int t=read();
while(t--)
{
init();
n=read(),m=read();
for(int i=1;i<=m;i++)
{
int a=read(),b=read();
Union(a,b);
}
printf("Scenario #%d:\n",++Case);
if(flag)
{
printf("Suspicious bugs found!\n");
}
else printf("No suspicious bugs found!\n");
puts("");
}
return 0;
}
emmmm就先写到这儿,以后有时间再补上……像可持久化并查集之类的……