对于欧拉回路,先判断出度入度的差是否为偶数,然后最大流一次。
此题是判断有无欧拉通路,前提要判断图是否连通,然后欧拉通路的条件:要么出入度差没有奇数,或者只有2个点。
所以先统计差为奇数的个数,如果不为0或2,不可能。然后如果为2,表示可能使欧拉路,所以此时可以将这两个点相连,类似添加一条无向边。然后就是判断是否为欧拉回路了。
#include<stdio.h> #include<string.h> #include<queue> #define maxn 50 #define INF 9999999 using namespace std; struct node { int to; int v; int flag; int next; }edge[1000*1000]; char s[1002][25]; int vis[maxn],pre[maxn],index,in[maxn],out[maxn],n,sum,t,ff; int pa[maxn]; int find(int x) { if(pa[x]!=x)pa[x]=find(pa[x]); return pa[x]; } void add(int x,int y,int z) { edge[index].to=y; edge[index].v=z; edge[index].flag=index+1; edge[index].next=pre[x]; pre[x]=index++; edge[index].to=x; edge[index].v=0; edge[index].flag=index-1; edge[index].next=pre[y]; pre[y]=index++; } int dfs(int u,int low) { int i; if(u==t) return low; for(i=pre[u];i!=-1;i=edge[i].next) { if(vis[edge[i].to]==vis[u]+1&&edge[i].v) { int a=dfs(edge[i].to,min(low,edge[i].v)); if(!a)continue; edge[i].v-=a; edge[edge[i].flag].v+=a; return a; } } return 0; } int BFS() { int i; queue<int>q; memset(vis,-1,sizeof(vis)); vis[0]=0; q.push(0); while(!q.empty()) { int t=q.front(); q.pop(); for(i=pre[t];i!=-1;i=edge[i].next) { if(vis[edge[i].to]<0&&edge[i].v) { vis[edge[i].to]=vis[t]+1; q.push(edge[i].to); } } } if(vis[t]>0) return 1; return 0; } void Dinic() { int ans=0; while(BFS()) { while(1) { int a=dfs(0,INF); if(!a)break; ans+=a; } } if(ans==sum) printf("Case %d: Well done!\n",++ff); else printf("Case %d: Poor boy!\n",++ff); } void slove(int fs) { int i,st,se;//欧拉路奇数点的开始结束点 st=se=-1; int count=0,flag=0; for(i=1;i<=‘z‘-‘a‘+1;i++) { if(in[i]||out[i]) { if(find(i)!=find(fs)) { flag=1; break; } else if((out[i]-in[i])%2!=0) { count++; if(st==-1)st=i; else se=i; } } } if(count!=0&&count!=2) flag=1; if(flag) printf("Case %d: Poor boy!\n",++ff); else { if(count==2) { add(st,se,1); out[st]++; in[se]++; } for(i=1;i<=‘z‘-‘a‘+1;i++) { if(out[i]>in[i]) { add(0,i,(out[i]-in[i])/2); sum+=((out[i]-in[i])/2); } else if(in[i]>out[i]) { add(i,t,(in[i]-out[i])/2); } } Dinic(); } } int init() { int i,fs; t=‘z‘-‘a‘+2; sum=0; index=1; for(i=0;i<=30;i++)pa[i]=i; memset(pre,-1,sizeof(pre)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); scanf("%d",&n); for(i=1;i<=n;i++) { int z; scanf("%s %d",s[i],&z); int l=strlen(s[i]); int x=s[i][0]-‘a‘+1; int y=s[i][l-1]-‘a‘+1; in[y]++,out[x]++,fs=x; int fx=find(x),fy=find(y); if(fx!=fy)pa[fx]=fy; if(z) { add(x,y,1); } } return fs; } int main() { ff=0; int t,father; scanf("%d",&t); while(t--) { father=init(); slove(father); } }
时间: 2024-10-25 02:19:17