HDU 6109 数据分割(并查集+set)

数据分割

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2457    Accepted Submission(s): 748

Problem Description
小w来到百度之星的赛场上,准备开始实现一个程序自动分析系统。

这个程序接受一些形如xi=xjxixj 的相等/不等约束条件作为输入,判定是否可以通过给每个 w 赋适当的值,来满足这些条件。

输入包含多组数据。
然而粗心的小w不幸地把每组数据之间的分隔符删掉了。
他只知道每组数据都是不可满足的,且若把每组数据的最后一个约束条件去掉,则该组数据是可满足的。

请帮助他恢复这些分隔符。
 
Input
1行:一个数字L,表示后面输入的总行数。

之后L行,每行包含三个整数,i,j,e,描述一个相等/不等的约束条件,若e=1,则该约束条件为xi=xj ,若e=0,则该约束条件为 xixj

i,j,L100000
xi,xj
Output
输出共T+1行。

第一行一个整数T,表示数据组数。

接下来T行的第i行,一个整数,表示第i组数据中的约束条件个数。
 
Sample Input
6 2 2 1 2 2 1 1 1 1 3 1 1 1 3 1 1 3 0
 
Sample Output
1 6
 

分析

本题一开始以为要用种类并查集做,但是本题和种类并查集不同的是,种类并查集应用的情况是固定的种类数,也就是非此即彼的情况,但是本题来说 1和2不同 2和3不同 未必代表1和3就相同

所以需要对于每一个根维护一个set 存储与其对立的根(注意是在根节点维护关于根的set,否则可能会出现遗漏)

对于a和b已经在同一个集的情况 ,如果约束条件为0 则代表到了本组最后一个条件,进行初始化

对于a和b不在同一个集的情况,如果约束条件为0 将彼此的根节点加入set中,如果约束条件为1 则遍历彼此根节点的set,如果不冲突就可以合并,注意合并的时候要把set一起合并,冲突的话说明到了本组最后一个条件,进行初始化

#include<bits/stdc++.h>
using namespace std;

int s[100005],anss[100005],num,sum,cnt,l,L,c,now,a[100005],b[100005];

set<int> st[100005];

int findf(int x)
{
    return x==s[x]?x:s[x]=findf(s[x]);
}

void hebing(int fa,int fb)
{
    s[fa]=fb;
    set<int>::iterator it;
    for(it=st[fa].begin();it!=st[fa].end();it++)   //“敌人”也要一起合并 
    {
        st[fb].insert(*it);
    }
    for(it=st[fb].begin();it!=st[fb].end();it++)
    {
        st[fa].insert(*it);
    }
 } 
 
int pd(int fa,int fb)
{
    if(st[fa].count(fb)||st[fb].count(fa))   //set中有冲突的根 
    {
        return 0;
    }
    else
    {
        return 1;
    }
 } 

void Init()
{
    for(int i=0;i<now;i++)
    {
        s[a[i]]=a[i];   //初始化根节点
        st[a[i]].clear(); //清空“敌人”
        s[b[i]]=b[i];   
        st[b[i]].clear();
    }
    now=0;
    anss[cnt++]=num;
    num=0;
}

int main()
{
    cin>>l;
    L=l;
    sum=0;
    cnt=0;
    now=0;
    for(int i=1;i<=L;i++)
    {
        s[i]=i;
    }
    while(l--)
    {
        cin>>a[now]>>b[now]>>c;
        num++;
        int fa=findf(a[now]);
        int fb=findf(b[now]);
        now++;
        if(fa==fb)       //已经在同一个类 
        {
            if(c==0)    //约束条件为不等
            {
                sum++;
                Init();
            } 
        }
        else   //现在还不在同一个类 
        {
            if(c==1)    //约束条件为相等 进行判断 
            {    
                if(pd(fa,fb)==1)   //不冲突 可以合并
                {
                    hebing(fa,fb);
                } 
                else
                {
                    sum++;
                    Init();
                } 
            }
            else       //约束条件为不等,加入set 
            {
                st[fa].insert(fb);   //均以根为标记 
                st[fb].insert(fa);
            }
        } 
    }
    cout<<sum<<endl;
    for(int i=0;i<cnt;i++)
    {
        cout<<anss[i]<<endl;
    } 
}
原文地址:https://www.cnblogs.com/dyhaohaoxuexi/p/12564905.html