题意:给你一些单词,一些单词可以正着也可以倒着,问你给你的单词表能不能连成一单词表。
想法:由题意要想到这题不只是判断是否是欧拉回路也可以是欧拉通路,以为单词表连起来就好了,没说是要连成环还是链。不了解这个的可以看之前的博客混合欧拉图。除此以外还有最重要的一点就是图的连通性。
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #define inf 0x7fffffff using namespace std; const int nodes=30; const int edges=2000+50; int n,s,t; int sum; int in[nodes],out[nodes]; struct node { int v,next; int flow; }e[edges]; int head[nodes],cnt,cur[nodes],father[nodes]; class Dinic { public: int spath() { queue<int>q; while(!q.empty()) q.pop(); memset(dis,-1,sizeof(dis)); dis[s]=0; q.push(s); while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i+1;i=e[i].next) { int v=e[i].v; if(dis[v]==-1&&e[i].flow>0) { dis[v]=dis[u]+1; q.push(v); } } } return dis[t]!=-1; } int Min(int a,int b) { if(a<b) return a; return b; } int dfs(int u,int flow) { int cost=0; if(u==t) return flow; for(int &i=cur[u];i+1;i=e[i].next) { int v=e[i].v; if(dis[v]==dis[u]+1&&e[i].flow>0) { int min=dfs(v,Min(e[i].flow,flow-cost)); if(min>0) { e[i].flow-=min; e[i^1].flow+=min; cost+=min; if(cost==flow) break; } else dis[v]=-1; } } return cost; } int result() { int res=0; while(spath()) { for(int i=s;i<=t;i++) cur[i]=head[i]; res+=dfs(s,inf); } return res; } private: int dis[nodes]; }dinic; void Init() { memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(head,-1,sizeof(head)); for(int i=1;i<=26;i++) father[i]=i; cnt=0; } void add(int a,int b,int c) { e[cnt].v=b; e[cnt].flow=c; e[cnt].next=head[a]; head[a]=cnt++; e[cnt].v=a; e[cnt].flow=0; e[cnt].next=head[b]; head[b]=cnt++; } int aabs(int x) { if(x>0) return x; return -x; } bool judge_unpass() { int num=0; for(int i=1;i<=26;i++) { int k=aabs(in[i]-out[i]); if(k%2==1) num++; } if(num!=0&&num!=2) return true; num=0; for(int i=1;i<=26;i++) if((in[i]+out[i])&&father[i]==i) num++; if(num>1) return true; return false; } void build_map() { s=0;t=27; sum=0; for(int i=1;i<=26;i++) { if(in[i]==0&&out[i]==0) continue; if(in[i]<out[i]) { add(s,i,aabs(in[i]-out[i])/2); sum+=aabs(in[i]-out[i])/2; } else add(i,t,aabs(in[i]-out[i])/2); } } int find(int x) { if(x!=father[x]) father[x]=find(father[x]); return father[x]; } void treatment() { int ans=dinic.result(); if(ans==sum) printf("Well done!\n"); else printf("Poor boy!\n"); } void union_set(int x,int y) { x=find(x); y=find(y); if(x==y) return; father[x]=y; } int main() { int ca=1,task; scanf("%d",&task); while(task--) { Init(); scanf("%d",&n); for(int i=1;i<=n;i++) { char str[25]; int key; scanf("%s%d",str,&key); int len=strlen(str); int u=str[0]-'a'+1; int v=str[len-1]-'a'+1; out[u]++;in[v]++; if(key) add(u,v,1); union_set(u,v); } printf("Case %d: ",ca++); if(judge_unpass()) { printf("Poor boy!\n"); continue; } build_map(); treatment(); } return 0; }