hdu 6109(并查集+set)

来源:互联网 发布:ubuntu 邮件 编辑:程序博客网 时间:2024/06/05 02:26

hdu 6109
思路:尽量让多的条件满足,当有一个条件和前面的冲突时,就是分隔符的时候,用并查集维护相同的数,set维护不同的数。当两个数在同一个并查集中时,代表两个数相同,不在同一个并查集是说明两个数可能相同也可能不同。当a在b的set中时代表b和a不相同。所以当我们每次判断两个数是否相同时先找并查集,并且要顺带更新set因为a==b,bc,所以ac但是这样每次更新一个并查集里面的所有元素复杂度太高一不好写,所以当每次找的时候我们只需要将子节点的set加到父节点的set理解好了然后判断两个祖先节点的set是否有出现过,有的话就代表ab

#include<set>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define LL long longusing namespace std;const int maxn=1e6+10;int fa[maxn],dep[maxn];//dep记录的是并查集的高度,用于将低树并到高树上set<int> s[maxn/10];//s[i]记录和i不相等的集合void init(int n)//初始化{    for(int i=1;i<=n;i++)    {        fa[i]=i;        dep[i]=0;        s[i].clear();    }}void push_up(int a,int b){    for(set<int>::iterator it=s[a].begin();it!=s[a].end();it++)        s[b].insert(*it);}int finds(int x){    if(x==fa[x])        return x;    push_up(x,fa[x]);//将儿子不相等的并到父亲的集合里    return fa[x]=finds(fa[x]);}void merger(int a,int b)//合并a,b{    a=finds(a),b=finds(b);    if(dep[a]<dep[b])        fa[a]=b;    else    {        fa[b]=a;        if(dep[a]==dep[b])            dep[a]++;    }}int ans[maxn];int main(){    int n;    while(~scanf("%d",&n))    {        init(n);        int cont=0,tot=0;        for(int i=0;i<n;i++)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            a=finds(a),b=finds(b);            tot++;            if(c)            {                if(a!=b)//当fa[a]和fa[b]不相同时a可能等于b也可能不等于                {                    if(s[a].count(b)||s[b].count(a))//fa[a]中有fa[b]或者fa[b]中有fa[a]则说明a和b不相等                    {                        ans[cont++]=tot;                        tot=0;                        init(n);                    }                    else//a和b相同                        merger(a,b);                }            }            else            {                if(a==b)//fa[a]和fa[b]在同一个并查集里说明a==b                {                    ans[cont++]=tot;                    tot=0;                    init(n);                }                else                {                    s[a].insert(b);                    s[b].insert(a);                }            }        }        printf("%d\n",cont);        for(int i=0;i<cont;i++)            printf("%d\n",ans[i]);    }}
原创粉丝点击