POJ 2513 Colored Sticks (离散化+并查集+欧拉通路)

下面两个写得很清楚了,就不在赘述。

http://blog.sina.com.cn/s/blog_5cd4cccf0100apd1.html
http://www.cnblogs.com/lyy289065406/archive/2011/07/30/2122265.html

我这里没用trie来表示颜色种类,而是用数组对颜色离散化,之后就差不多一样了,用并查集判断是否连通,再判断奇顶点的个数是否为0个或2个。

这题我开始大意了,刚开始就只判断奇数度的节点个数是否为0或2,没有考虑判断图的连通性。
以后要注意碰到图的问题要考虑连通性的问题。

#include <iostream>
#include <stdio.h>
#include <map>
#include <string.h>
#include <algorithm>
#include <string>

using namespace std;
const int maxn=500005;
int num[maxn];  //存储某颜色出现的个数
int idx=1;
int cnt;
int idxw=1;

struct Wood{
    char left[12],right[12];
}wood[maxn/2];

struct Node{
    char str[12];  //存储颜色
    bool operator<(const Node tmp)const{
        if(strcmp(str,tmp.str)<=0)
            return true;
        else
            return false;
    }
}node[maxn];
//二分查找颜色对应离散的值
int binarySearch(char*str){
    int l=0,r=cnt+1,mid;
    while(r-l>1){
        mid=(r+l)/2;
        if(strcmp(node[mid].str,str)<=0)
            l=mid;
        else
            r=mid;
    }
    return l;
}
struct UF{
    int fa[maxn];
    void init(){
        for(int i=0;i<maxn;i++)
            fa[i]=i;
    }
    int find_root(int x){
        if(fa[x]!=x)
            fa[x]=find_root(fa[x]);
        return fa[x];
    }
    void Union(int a,int b){
        int x=find_root(a);  //一开始这里写错了,括号里的写成了x和y。。。导致一直WA。。。
        int y=find_root(b);
        fa[y]=x;
    }
}uf;
int main()
{
    char s1[12],s2[12];
    while(scanf("%s%s",wood[idxw].left,wood[idxw].right)!=EOF){
        strcpy(node[idx++].str,wood[idxw].left);
        strcpy(node[idx++].str,wood[idxw].right);
        idxw++;
    }
    sort(node+1,node+idx);
    memset(num,0,sizeof(num));
    cnt=1;
    num[1]++;
    //进行离散处理,同时统计每种颜色出现的个数
    for(int i=2;i<idx;i++){
        if(strcmp(node[i].str,node[i-1].str)!=0){
            strcpy(node[++cnt].str,node[i].str);
            num[cnt]++;
        }
        else{
            num[cnt]++;
        }
    }
    int u,v;
    uf.init();
    for(int i=1;i<idxw;i++){
        u=binarySearch(wood[i].left);
        v=binarySearch(wood[i].right);
        uf.Union(u,v);
    }
    int c=0,eular=0;  //c为连通分支的个数,如果为1,表明图连通;eular为奇顶点的个数。
    for(int i=1;i<=cnt;i++){
        if(uf.fa[i]==i){
            c++;
        }
        if(num[i]%2==1){
            eular++;
        }
    }
    //idxw==1表明数据为空,要输出Possible,这点要注意!
    //所有点都在同一个集合,且某颜色出现次数为奇数的只能为0个或2个,即存在欧拉通路。
    if(idxw==1 || (c==1&&(eular==0||eular==2))){
        printf("Possible
");
    }
    else
        printf("Impossible
");
    return 0;
}
原文地址:https://www.cnblogs.com/chenxiwenruo/p/3535156.html