此题中涉及三个小算法,这是一个无向图判断欧拉回路,
无向图存在欧拉回路的充要条件
一个无向图存在欧拉回路,当且仅当该图只存在0或2个奇数度数的顶点,且该图是连通图。
有向图存在欧拉回路的充要条件
一个有向图存在欧拉回路,所有顶点的入度等于出度且该图是连通图。
判断度数很简单,当时没想明白怎么判断图示连通的,其实只要判断他们的父节点的个数,只要只有一个父节点,那么此图是连通的。
字典树分配一下他们的id就好了,还有卡住的一点就是零图是欧拉图。
还有我做了一个小小的剪芝,但是没有什么效果,只减少了30ms
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; int cnt; int par[500050]; char s1[20],s2[20]; int deg[500050]; struct node { int id; node *next[26]; node (){ for(int i=0;i<26;i++) next[i]=NULL; id=0; } }*root; int Insert(char s[]){ int len = strlen (s); node *p=root; for(int i=0;i<len;i++){ if(p->next[s[i]-'a']==NULL) p->next[s[i]-'a']=new node(); p=p->next[s[i]-'a']; } if(!p->id) return p->id=++cnt; else return p->id; } int findset(int x){ if(x!=par[x]) par[x]=findset(par[x]); return par[x]; } void unite(int x,int y){ int px=findset(x); int py=findset(y); if(px!=py){ par[py]=px; } } bool con(){ int k=0; for(int i=1;i<=cnt;i++){ if(findset(i)==i) k++; if(k>1) return 0;//剪枝处 } return 1; } bool oula(){ int k=0; for(int i=1;i<=cnt;i++){ if(deg[i]&1) k++; if(k>2) return 0;//剪枝处 } if(k==0||k==2) return 1; return 0; } int main(){ root = new node (); for(int i=0;i<500050;i++) par[i]=i; memset(deg,0,sizeof(deg)); cnt=0; while(scanf("%s%s",s1,s2)!=EOF){ int u=Insert(s1); int v=Insert(s2); deg[u]++; deg[v]++; unite(u,v); } if(cnt==0) puts("Possible");//当他们是零图的时候 else { if(oula()&&con()) puts("Possible"); else puts("Impossible"); } }
时间: 2024-11-05 17:33:28