题意:有一些木棍,每根木棍两端各有一种颜色,两个有相同颜色的端可以连在一起,问这些木棍能不能连成一条线。
把颜色看作点,木棍看作边,转化为求图中有没有欧拉路,无向图有欧拉路等价于无向图联通且奇度点为两个或零个,证明略。
判断联通用并查集,点的度直接统计即可。
问题在于把字符串映射成int,stlmap太慢,用trie实现。
(因为有零根木棍的情况WA了一下午...)
#include <cstdio> #include<map> #include<iostream> #include<string> #include<cstring> using namespace std; typedef long long int LL; #define st first #define nd second #define pb push_back #define mp make_pair #define pll pair <LL, LL> #define pii pair <int, int> #define rep(i,x) for(int i=1;i<=x;i++) const int N = 5e5+7; const int MX = 1e9+7; const LL INF = 1e18+9LL; const int mod = 20071027; int n,odd,cnt; int fa[N],deg[N],sz[N]; struct Trie{ int val[600010],ch[600010][26]; int sz; void init(){ memset(ch[0],0,sizeof(ch[0])); sz=1; } int index(char c){return c-'a';} void insert(char* a,int v){ int u=0,l=strlen(a); for(int i=0;i<l;i++){ int x=index(a[i]); if(!ch[u][x]){ memset(ch[sz],0,sizeof(ch[sz])); val[sz]=0; ch[u][x]=sz++; } u=ch[u][x]; } val[u]=v; } int find(char* a){ int u=0,l=strlen(a); for(int i=0;i<l;i++){ int x=index(a[i]); if(!ch[u][x])return 0; u=ch[u][x]; } return val[u]; } }trie; int find(int x){ if(fa[x]==x)return x; return fa[x]=find(fa[x]); } void merge(int x,int y){ deg[x]++; deg[y]++; int fx=find(x); int fy=find(y); fa[fx]=fy; if(fx!=fy)sz[fy]+=sz[fx]; } int main(){ char a[12],b[12]; rep(i,N-1)fa[i]=i,sz[i]=1; trie.init(); while(scanf("%s%s",a,b)==2){ if(!trie.find(a))trie.insert(a,++cnt); if(!trie.find(b))trie.insert(b,++cnt); merge(trie.find(a),trie.find(b)); } rep(i,cnt)if(deg[i]%2)odd++; if(sz[find(1)]>=cnt&&(odd==2||odd==0))printf("Possible "); else printf("Impossible "); }