• PKU 2513 Colored Sticks(并查集+Trie树+欧拉路径(回路))


    题目大意:

    给定一些木棒,木棒两端都涂上颜色,求是否能将木棒首尾相接,连成一条直线,要求不同木棒相连接的一端必须是同颜色的。

    解题思路:

    可以用图论中欧拉路的知识来解这道题,首先可以把木棒两端看成节点,把木棒看成边,这样相同的颜色就是同一个节点

    问题便转化为:给定一个图,是否存在一笔画”经过涂中每一点,每条边一次。

    这样就是求图中是否存在欧拉路Euler-Path

    关于度数的判断方法:

    节点的度用颜色出现次数来统计,如样例中,蓝色blue出现三次(不管是出度还是入度),那么blue结点的度就为3,同样地,我们也可以通过输入得到其他全部结点的度,于是,我们有:

    Magenta=2

    Blue=3

    Red=2

    Violet=1

    Cyan=2

    用一个一维数组就能记录了,然后分别模2,就能判断颜色结点的奇偶性

    只要奇度数的结点数的个数=1或>=3,即使图连通,也一定不存在欧拉路径

    Trie树+并查集+欧拉路径

    #include<cstdio>
    #include<cstdlib>
    #define maxn 500010
    typedef struct Trie{
        int pos;
        struct Trie *next[26];
    }Trie,*trie;
    trie root;
    int k=0,fa[maxn],d[maxn];
    void Init(trie &p)
    {
        p=(trie)malloc(sizeof(Trie));
        for(int i=0;i<26;i++) p->next[i]=NULL;
        p->pos=0;
    }//建Trie树,返回单词编号 
    int Build(trie &p,char *s,int depth)
    {
        if(!s[depth]){
            if(p->pos) return p->pos;
            p->pos=++k;
            fa[k]=k,d[k]=0;//初始化祖先为自身,度数为0 
            return k;
        }//q不能定义为全局变量 
        trie q=p->next[s[depth]-'a'];
        if(q==NULL){
            Init(q);
            p->next[s[depth]-'a']=q;
        }
        return Build(q,s,depth+1);
    }
    int Findset(int x)
    {
        if(fa[x]==x) return x;
        return fa[x]=Findset(fa[x]);
    }
    void Union(int u,int v)
    {
        int x=Findset(u);
        int y=Findset(v);
        if(x!=y) fa[x]=y;
    }
    int main()
    {
        Init(root);
        char s[12],t[12];
        while(scanf("%s%s",s,t)!=EOF){
            int x=Build(root,s,0);
            int y=Build(root,t,0);
            Union(x,y);
            d[x]++,d[y]++;
        }
        int scc=0,odd=0;
        for(int i=1;i<=k;i++){
            if(fa[i]==i) scc++;//不连通 
            if(d[i]&1) odd++;//奇度节点
        }
        if(scc>1||odd>2) puts("Impossible");
        else puts("Possible");
        return 0;
    }

    离散化+并查集+欧拉路径

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 500010
    using namespace std;
    int num[maxn],fa[maxn];
    int idxc=1,idxw=1,cnt;
    
    struct Wood{
        char left[12],right[12];
    }wood[maxn/2];
    struct Node{
        char col[12];  
        bool operator<(const Node tmp)const{
            if(strcmp(col,tmp.col)<=0)
                return true;
            return false;
        }
    }node[maxn];
    //二分查找颜色对应离散的编号 
    int Binary_Search(char *col){
        int l=0,r=cnt+1;
        while(r-l>1){
            int mid=(r+l)/2;
            if(strcmp(node[mid].col,col)<=0) l=mid;
            else r=mid;
        }
        return l;
    }
    int Findset(int x)
    {
        if(fa[x]!=x) 
            fa[x]=Findset(fa[x]);
        return fa[x];
    }
    
    int main()
    {
        char s1[12],s2[12];
        while(scanf("%s%s",wood[idxw].left,wood[idxw].right)!=EOF){
            strcpy(node[idxc++].col,wood[idxw].left);
            strcpy(node[idxc++].col,wood[idxw].right);
            idxw++;
        }
        sort(node+1,node+idxc);
        memset(num,0,sizeof(num));
        num[1]++,cnt=1;
        for(int i=2;i<idxc;i++){//进行离散处理,同时统计每种颜色出现的个数
            if(strcmp(node[i].col,node[i-1].col)!=0){
                strcpy(node[++cnt].col,node[i].col);
                num[cnt]++;//颜色不同保留下来
            }
            else num[cnt]++;//颜色相同直接计数
        }
        for(int i=1;i<maxn;i++) fa[i]=i;
        for(int i=1;i<idxw;i++){
            int u=Binary_Search(wood[i].left);
            int v=Binary_Search(wood[i].right);
            int x=Findset(u),y=Findset(v);  
            if(x!=y) fa[x]=y;
        }
        int scc=0,odd=0;//cnt是节点编号,也是节点个数 
        for(int i=1;i<=cnt;i++){
            if(fa[i]==i) scc++;
            if(num[i]%2) odd++;
        }
        if(idxw==1||(scc==1&&(odd==0||odd==2))) printf("Possible
    ");
        else printf("Impossible
    ");
    }
  • 相关阅读:
    地三鲜
    在linux下使用am335x的DMA
    通过tarball形式安装HBASE Cluster(CDH5.0.2)——集群安装总览
    通过tarball形式安装HBASE Cluster(CDH5.0.2)——如何配置分布式集群中的zookeeper
    如何通过SSH及其Client 批量分发文件和执行管理命令
    解决ESXi有虚拟机模版部署的CentOS虚拟机,网卡eth0找不到问题
    CentOS 65 安装vmware tools 杂记
    安装vmware vCenter Appliance
    使用FileZilla解决从Windows上传文件到Linux vsftpd的乱码问题!
    不关闭seLinux解决vsftpd服务本地用户不能登录问题(500 OOPS: cannot change directory:/home/***)
  • 原文地址:https://www.cnblogs.com/freinds/p/6407803.html
Copyright © 2020-2023  润新知