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\n");
    }
    else
        printf("Impossible\n");
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM