hdu6109(并查集+启发式合并)

来源:互联网 发布:免费杀木马软件 编辑:程序博客网 时间:2024/05/19 14:53

题面
题意就是有n个数,不断给你条件,如i=j或i!=j
你要把条件扔进一个栈里。
若出现一个条件和栈里的条件出现冲突
输出栈的大小+1&&清空栈

等于是满足传递性的,故等于关系可以用并查集维护,同一个集合的表示它们都相等。
若出现不等关系,且它们在同一个集合里,则冲突,否则这两个点连一条边

如果来了一个相等关系,且它们所在的两个集合之间有连边,则冲突,否则合并这两个集合。

具体实现就是启发式合并,两个点连边等价于在两个点所在集合的根结点连边。
合并两个集合时就把和“边数较小的集合的根”有关的边,一条一条接到另一个集合的根上。
对于每一条边,每合并一次它所在的集合边数至少*2,故它的合并次数都不会超过log(n)。

这种noip难度的题比赛没做出来有点可惜

这个程序跑得飞快

#include <iostream>#include <fstream>#include <algorithm>#include <cmath>#include <ctime>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;#define mmst(a, b) memset(a, b, sizeof(a))#define mmcp(a, b) memcpy(a, b, sizeof(b))typedef long long LL;const int N=100100,M=2002000;int m,n,mx;int fa[N];int ans[N],top;int cnt,to[M],head[N],num[N],nex[M];void init(int x){    for(int i=0;i<=x;i++)    {        fa[i]=i;        num[i]=head[i]=0;    }    mx=0;    cnt=1;}void add(int u,int v){    num[u]++;    to[++cnt]=v;    nex[cnt]=head[u];    head[u]=cnt;}int find(int x){    if(fa[x]==x)    return x;    fa[x]=find(fa[x]);    return fa[x];}bool unite(int a,int b){    if(a!=b)    {        if(num[a]>num[b])        swap(a,b);        num[b]+=num[a];        fa[a]=b;        int last=0;        for(int h=head[a];h;h=nex[h])        {            if(to[h]==b)            return false;            to[h^1]=b;            last=h;        }        if(last)        {            nex[last]=head[b];            head[b]=head[a];        }    }    return true;}int main(){    cin>>n;    init(100000);    int now=0,u,v,ops;    for(;;)    {        now++;        bool ok=true;        scanf("%d%d%d",&u,&v,&ops);        mx=max(mx,u);        mx=max(mx,v);        u=find(u);        v=find(v);        if(!ops)        {            if(u==v)            ok=false;            add(u,v);            add(v,u);        }        else        if(!unite(u,v))        ok=false;        if(!ok)        {            ans[++top]=now;            init(mx);        }        if(now==n)        break;    }    cout<<top<<endl;    for(int i=1;i<=top;i++)    printf("%d\n",ans[i]-ans[i-1]);    return 0;}
阅读全文
2 0
原创粉丝点击