HDU 6109 数据分割(并查集+set+在线倍增法)

来源:互联网 发布:url scheme windows 编辑:程序博客网 时间:2024/05/16 11:10

Description

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

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

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

请帮助他恢复这些分隔符。

Input

1行:一个数字L,表示后面输入的总行数。

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

i,j,L100000

xi,xjL

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

Solution1

用并查集维护相等关系,用set维护不相等关系

x=y时,看xset里是否有y,如果有说明与之前的限制矛盾,当前这个限制是一组数据末尾,否则在并查集中合并xy,假设将x合并到y中,则之前xset中与x不同的数zy也不同,故把zy 分别加入到对方的set中表示这两个数不同,并把zxset中删去

xy时,看并查集中xy是否属于同一个集合,属于则矛盾,当前这个限制是一组数据末尾,否则把xy 分别加入到对方的set中表示这两个数不同

Code1

#include<cstdio>#include<set>#include<vector>using namespace std;namespace fastIO {    #define BUF_SIZE 100000    //fread -> read    bool IOerror=0;    inline char nc()     {        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;        if(p1==pend)         {            p1=buf;            pend=buf+fread(buf,1,BUF_SIZE,stdin);            if(pend==p1)             {                IOerror=1;                return -1;            }        }        return *p1++;    }    inline bool blank(char ch)     {        return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';    }    inline void read(int &x)     {        char ch;        while(blank(ch=nc()));        if(IOerror)return;        for(x=ch-'0';(ch=nc())>='0'&&ch<='9';x=x*10+ch-'0');    }    #undef BUF_SIZE};using namespace fastIO;#define maxn 100005int fa[maxn];int find(int x){    if(fa[x]==x)return x;    return fa[x]=find(fa[x]);}set<int>s[maxn],ss;set<int>::iterator it;void init(){    for(it=ss.begin();it!=ss.end();it++)        fa[*it]=*it,s[*it].clear();    ss.clear();}vector<int>ans;int main(){    for(int i=1;i<=100000;i++)fa[i]=i;    int L,x,y,e,num=0;    read(L);    //scanf("%d",&L);    while(L--)    {        num++;        read(x),read(y),read(e);        //scanf("%d%d%d",&x,&y,&e);        x=find(x),y=find(y);        ss.insert(x),ss.insert(y);        if(e)        {            if(x==y)continue;            if(s[x].find(y)!=s[x].end())            {                ans.push_back(num);                num=0;                init();            }            else            {                for(it=s[x].begin();it!=s[x].end();it++)                {                    s[y].insert(*it);                    s[*it].insert(y);                    s[*it].erase(x);                }                fa[x]=y;            }        }        else        {            if(x!=y)            {                s[x].insert(y);                s[y].insert(x);            }            else             {                ans.push_back(num);                num=0;                init();            }           }    }    printf("%d\n",ans.size());    for(int i=0;i<ans.size();i++)printf("%d\n",ans[i]);    return 0;}

Solution2

并查集维护相等关系,倍增求每组数据的长度,先把限制中相等关系的用并查集合并,之后判断不相等关系是否在同一集合中

Code2

#include<cstdio>#include<set>#include<vector>using namespace std;namespace fastIO {    #define BUF_SIZE 100000    //fread -> read    bool IOerror=0;    inline char nc()     {        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;        if(p1==pend)         {            p1=buf;            pend=buf+fread(buf,1,BUF_SIZE,stdin);            if(pend==p1)             {                IOerror=1;                return -1;            }        }        return *p1++;    }    inline bool blank(char ch)     {        return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';    }    inline void read(int &x)     {        char ch;        while(blank(ch=nc()));        if(IOerror)return;        for(x=ch-'0';(ch=nc())>='0'&&ch<='9';x=x*10+ch-'0');    }    #undef BUF_SIZE};using namespace fastIO;#define maxn 100005int n,x[maxn],y[maxn],e[maxn],fa[maxn];int find(int x){    if(fa[x]==x)return x;    return fa[x]=find(fa[x]);}int unite(int x,int y){    x=find(x),y=find(y);    if(x!=y)fa[x]=y;}bool check(int l,int r){    if(r>n)return 0;    for(int i=l;i<=r;i++)        if(e[i])unite(x[i],y[i]);    for(int i=l;i<=r;i++)        if(!e[i]&&(find(x[i])==find(y[i])))        {            for(int j=l;j<=r;j++)fa[x[j]]=x[j],fa[y[j]]=y[j];            return 0;        }    return 1;}vector<int>ans;int main(){    read(n);    //scanf("%d",&n);    for(int i=0;i<=n;i++)fa[i]=i;    for(int i=1;i<=n;i++)read(x[i]),read(y[i]),read(e[i]);//scanf("%d%d%d",&x[i],&y[i],&e[i]);    for(int i=1;i<=n;)    {        int j=i,d=1;        while(check(i,j+d))        {            while(check(i,j+2*d))d<<=1;            j+=d;            d=1;        }        if(j+d<=n)ans.push_back(j+d-i+1);        i=j+d+1;    }    printf("%d\n",ans.size());    for(int i=0;i<ans.size();i++)printf("%d\n",ans[i]);    return 0;}
阅读全文
0 0
原创粉丝点击