下面兩個寫得很清楚了,就不在贅述。
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; }
