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; }