#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=(1<<28);
const int point_num=500;
int cap[point_num][point_num],dist[point_num],gap[point_num];//初始化见main里面
int s0,t0,n;//源,汇和点数
int find_path(int p,int limit=0x3f3f3f3f)
{
if(p==t0) return limit;
for(int i=0;i<n;i++)
if(dist[p]==dist[i]+1 && cap[p][i]>0)
{
int t=find_path(i,min(cap[p][i],limit));
if(t<0) return t;
if(t>0)
{
cap[p][i]-=t;
cap[i][p]+=t;
return t;
}
}
int label=n;
for(int i=0;i<n;i++) if(cap[p][i]>0) label=min(label,dist[i]+1);
if(--gap[dist[p]]==0 || dist[s0]>=n ) return -1;
++gap[dist[p]=label];
return 0;
}
int sap()
{
memset(dist,0,sizeof(dist));
memset(gap,0,sizeof(gap));
//初始化s,t
s0=0,t0=n-1;
int t=0,maxflow=0;
gap[0]=n;
while((t=find_path(s0))>=0) maxflow+=t;
return maxflow;
}
//并查集判断联通
int used[point_num];
int fath[point_num];
int find(int x)
{
return fath[x]==x?x:fath[x]=find(fath[x]);
}
void uion(int x,int y)
{
x=find(x),y=find(y);
if(x==y) return ;
fath[x]=y;
}
//入度+出度 构造网络流模型
int _abs(int x){return x>0?x:-x;}
int in[point_num],out[point_num];
int main()
{
int ci,pl=1;scanf("%d",&ci);
while(ci--)
{
memset(cap,0,sizeof(cap));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(used,0,sizeof(used));
for(int i=1;i<=point_num;i++) fath[i]=i;//并查集判断联通
int point ,edge;
point=26;
scanf("%d",&edge);
char ch[100];
for(int i=0;i<edge;i++)
{
int x,y,d;scanf("%s%d",ch,&d);//从1开始
x=ch[0]-'a'+1;y=ch[strlen(ch)-1]-'a'+1;
uion(x,y);
used[x]=used[y]=1;
if(d==1) cap[x][y]++;//无向图 添加最大流量为1的流
in[y]++,out[x]++;//定义x->y;
}
int flag=1;
//判断联通
int fath1=-1;
for(int i=1;i<=point;i++)
{
if(used[i]==0) continue;
if(fath1==-1)
{
fath1=find(i);
continue;
}
if(find(i)!=fath1)
{
flag=0;break;
}
}
//判断入度 出度是否满足条件
int tp=0;
for(int i=1;i<=point;i++)
{
if(used[i]==0) continue;
if(_abs(in[i]-out[i])%2)
{
if(in[i]>out[i]) tp++;
else tp+=10000;
}
}
if(!(tp==10001||tp==0)) flag=0;
if(!flag) {printf("Case %d: Poor boy!\n",pl++);continue;}
//构建网络流模型
int maxFlow=0;//最大流
n=point+2;//添加源点0,汇点point+1 总点数为point+2
for(int i=1;i<=point;i++)
{
if(in[i]-out[i]>0) cap[i][n-1]=(in[i]-out[i])/2;
else if(in[i]-out[i]<0) cap[0][i]=(out[i]-in[i])/2,maxFlow+=cap[0][i];
else ;
}
int cnt=sap();
if(cnt==maxFlow) printf("Case %d: Well done!\n",pl++);//如果是满流,则是欧拉回路
else printf("Case %d: Poor boy!\n",pl++);
}
return 0;
}
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int inf=(1<<28);
const int point_num=500;
int cap[point_num][point_num],dist[point_num],gap[point_num];//初始化见main里面
int s0,t0,n;//源,汇和点数
int find_path(int p,int limit=0x3f3f3f3f)
{
if(p==t0) return limit;
for(int i=0;i<n;i++)
if(dist[p]==dist[i]+1 && cap[p][i]>0)
{
int t=find_path(i,min(cap[p][i],limit));
if(t<0) return t;
if(t>0)
{
cap[p][i]-=t;
cap[i][p]+=t;
return t;
}
}
int label=n;
for(int i=0;i<n;i++) if(cap[p][i]>0) label=min(label,dist[i]+1);
if(--gap[dist[p]]==0 || dist[s0]>=n ) return -1;
++gap[dist[p]=label];
return 0;
}
int sap()
{
memset(dist,0,sizeof(dist));
memset(gap,0,sizeof(gap));
//初始化s,t
s0=0,t0=n-1;
int t=0,maxflow=0;
gap[0]=n;
while((t=find_path(s0))>=0) maxflow+=t;
return maxflow;
}
//并查集判断联通
int used[point_num];
int fath[point_num];
int find(int x)
{
return fath[x]==x?x:fath[x]=find(fath[x]);
}
void uion(int x,int y)
{
x=find(x),y=find(y);
if(x==y) return ;
fath[x]=y;
}
//入度+出度 构造网络流模型
int _abs(int x){return x>0?x:-x;}
int in[point_num],out[point_num];
int main()
{
int ci,pl=1;scanf("%d",&ci);
while(ci--)
{
memset(cap,0,sizeof(cap));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
memset(used,0,sizeof(used));
for(int i=1;i<=point_num;i++) fath[i]=i;//并查集判断联通
int point ,edge;
point=26;
scanf("%d",&edge);
char ch[100];
for(int i=0;i<edge;i++)
{
int x,y,d;scanf("%s%d",ch,&d);//从1开始
x=ch[0]-'a'+1;y=ch[strlen(ch)-1]-'a'+1;
uion(x,y);
used[x]=used[y]=1;
if(d==1) cap[x][y]++;//无向图 添加最大流量为1的流
in[y]++,out[x]++;//定义x->y;
}
int flag=1;
//判断联通
int fath1=-1;
for(int i=1;i<=point;i++)
{
if(used[i]==0) continue;
if(fath1==-1)
{
fath1=find(i);
continue;
}
if(find(i)!=fath1)
{
flag=0;break;
}
}
//判断入度 出度是否满足条件
int tp=0;
for(int i=1;i<=point;i++)
{
if(used[i]==0) continue;
if(_abs(in[i]-out[i])%2)
{
if(in[i]>out[i]) tp++;
else tp+=10000;
}
}
if(!(tp==10001||tp==0)) flag=0;
if(!flag) {printf("Case %d: Poor boy!\n",pl++);continue;}
//构建网络流模型
int maxFlow=0;//最大流
n=point+2;//添加源点0,汇点point+1 总点数为point+2
for(int i=1;i<=point;i++)
{
if(in[i]-out[i]>0) cap[i][n-1]=(in[i]-out[i])/2;
else if(in[i]-out[i]<0) cap[0][i]=(out[i]-in[i])/2,maxFlow+=cap[0][i];
else ;
}
int cnt=sap();
if(cnt==maxFlow) printf("Case %d: Well done!\n",pl++);//如果是满流,则是欧拉回路
else printf("Case %d: Poor boy!\n",pl++);
}
return 0;
}