poj2513--并查集+欧拉路+字典树
经典好题,自己不知道哪里错了交上去是RE,可能是数组开的不好吧,字典树老碰到这种问题。。
先马上别人的代码,有空对拍看看
#include <cstdio> #include <cstring> int const MAX = 500005; int fa[MAX], d[MAX], cnt; struct Trie { int sz, t[MAX][15]; int jud[MAX]; Trie() { sz = 1; memset(t[0], -1, sizeof(t)); jud[0] = 0; } void clear() { sz = 1; memset(t[0], -1, sizeof(t)); jud[0] = 0; } int idx(char c) { return c - 'a'; } void insert(char* s, int v) { int u = 0, len = strlen(s); for(int i = 0; i < len; i++) { int c = idx(s[i]); if(t[u][c] == -1) { memset(t[sz], -1, sizeof(t[sz])); jud[sz] = 0; t[u][c] = sz++; } u = t[u][c]; } jud[u] = v; } int search(char* s) { int u = 0, len = strlen(s); for(int i = 0; i < len; i++) { int c = idx(s[i]); if(t[u][c] == -1) return -1; u = t[u][c]; } if(jud[u]) return jud[u]; return -1; } }t; void Init() { for(int i = 0; i < MAX; i++) fa[i] = i; } int Find(int x) { return x == fa[x] ? x : fa[x] = Find(fa[x]); } void Union(int a, int b) { int r1 = Find(a); int r2 = Find(b); if(r1 != r2) fa[r1] = r2; } bool eluer() { int sum = 0, t = -1; for(int i = 1; i < cnt; i++) if(d[i] % 2) sum++; if(sum != 0 && sum != 2) return false; for(int i = 1; i < cnt; i++) { if(t == -1) t = Find(i); else if(Find(i) != Find(t)) return false; } return true; } int main() { char s1[20],s2[20]; cnt = 1; Init(); t.clear(); while(scanf("%s %s", s1, s2) != EOF) { if(t.search(s1) == -1) t.insert(s1, cnt++); int u = t.search(s1); if(t.search(s2) == -1) t.insert(s2, cnt++); int v = t.search(s2); Union(u, v); d[u]++; d[v]++; } if(eluer()) printf("Possible\n"); else printf("Impossible\n"); }
下面是RE代码
/* 1 2 2 3 4 1 1 5 5 4 1 5,5 4,4 1,1 2,2 3 数据量大,不能用map 建立字典树,保留每个颜色的id 更新每个颜色的度,只要一个颜色的度为奇数,cnt1++ 用并查集保存图的连通性,如果最后剩下两个集,那么图不连通 注意:每个颜色都是一个点,每根木棒连接两个颜色,这就可以看做是并查集的连接 500*26 */ #include<iostream> #include<cstring> #include<cstdio> using namespace std; struct Trie{ int next[500005][15]; int id[500005]; int root,L,cnt; int newnode(){ for(int i=0;i<15;i++) next[L][i]=-1; id[L]=0; return L++; } void init(){ L=cnt=0; root=newnode(); } int insert(char s[]){ //cout << s << cnt<<endl; int len=strlen(s); int now=root; for(int i=0;i<len;i++){ if(next[now][s[i]-'a']==-1) next[now][s[i]-'a']=newnode(); now=next[now][s[i]-'a']; } if(id[now]==0) id[now]=++cnt; return id[now]; } }tr; int degree[25000*20]; int F[25000*20]; int find(int x){ if(F[x]==-1) return x; return F[x]=find(F[x]); } void bing(int a,int b){ int t1=find(a); int t2=find(b); if(t1!=t2) F[t1]=t2; } int main(){ tr.init(); memset(degree,0,sizeof degree); memset(F,-1,sizeof F); char s1[15],s2[15]; while(scanf("%s%s",s1,s2)!=EOF){ int id1=tr.insert(s1); int id2=tr.insert(s2); degree[id1]++; degree[id2]++; bing(id1,id2); } int cnt1=0,cnt2=0;//度为奇数的颜色,联通块 for(int i=1;i<=tr.cnt;i++){ if(degree[i]%2==1) cnt1++; if(F[i]==-1) cnt2++; if(cnt1>2) break; if(cnt2>1) break; } if ((cnt2==0 || cnt2==1) && (cnt1==0 || cnt1==2)) puts("Possible"); else puts("Impossible"); return 0; }