题目链接
有N个字符,如果字符可以首尾相同字符相接组成一条链的话,那么就是说明是well done的,不然,就不是,所以考虑成一条边,我们把每个字符串考虑成有向边,又有些字符串是可以反转的,实际上可以把它当成是无向边来考虑,现在,就是要知道,构成一个半欧拉图,也就是欧拉通路需要将这几条无向边怎样变化,或者不可能组成一个欧拉通路。
其实,与混合欧拉图不同的混合半欧拉图,与其对应的欧拉图的差别就是在于出现了两个度可以为奇数的点。怎样处理这两个点,成为了本题的最重要的难点了。
我们来看看欧拉图与半欧拉图之间的差别,再做定夺:
- 欧拉图没有奇数度的点,半欧拉图可以有一对(两个)奇数度的点
- 对于半欧拉图的两个始末点(也就是两个奇数度的点)有向链接就可以构成欧拉图
以第一条性质为基础的第二条性质,其实也就是解决这道题的关键之所在了,我们可以对这个不是欧拉图的半欧拉图,加一条边构建成欧拉图,而且,我们加入的这条边还是可以改变方向的,所以,我们把加入的这条边当成无向边来使。
于是,问题回到了解决混合欧拉图的问题上来了,而解决混合欧拉图,我们已经有了先例。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
//#define INF 10000007.
#define eps 1e-7
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 30, maxM = 1e3 + 37;
int N, M, in_du[maxN], out_du[maxN], root[maxN];
int fid(int x) { return x == root[x] ? x : root[x] = fid(root[x]); }
int head[maxN], cnt, cur[maxN];
bool used[maxN];
struct Eddge
{
int nex, to, flow;
Eddge(int a=-1, int b=0, int c=0):nex(a), to(b), flow(c) {}
}edge[maxM << 1];
inline void addEddge(int u, int v, int w)
{
edge[cnt] = Eddge(head[u], v, w);
head[u] = cnt++;
}
inline void _add(int u, int v, int w) { addEddge(u, v, w); addEddge(v, u, 0); }
struct Max_Flow
{
int S, T, n;
int gap[maxN], d[maxN], que[maxN], ql, qr;
inline void init()
{
n = T;
for(int i=S; i<=T; i++)
{
gap[i] = d[i] = 0;
cur[i] = head[i];
}
++gap[d[T] = 1];
que[ql = qr = 1] = T;
while(ql <= qr)
{
int x = que[ql ++];
for(int i=head[x], v; ~i; i=edge[i].nex)
{
v = edge[i].to;
if(!d[v]) { ++gap[d[v] = d[x] + 1]; que[++qr] = v; }
}
}
}
inline int aug(int x, int FLOW)
{
if(x == T) return FLOW;
int flow = 0;
for(int &i=cur[x], v; ~i; i=edge[i].nex)
{
v = edge[i].to;
if(d[x] == d[v] + 1)
{
ll tmp = aug(v, min(FLOW, edge[i].flow));
flow += tmp; FLOW -= tmp; edge[i].flow -= tmp; edge[i ^ 1].flow += tmp;
if(!FLOW) return flow;
}
}
if(!(--gap[d[x]])) d[S] = n + 1;
++gap[++d[x]]; cur[x] = head[x];
return flow;
}
inline int max_flow()
{
init();
int ret = aug(S, INF);
while(d[S] <= n) ret += aug(S, INF);
return ret;
}
} MF;
inline void init()
{
cnt = 0; MF.S = 0; MF.T = 27;
for(int i=0; i<=27; i++)
{
root[i] = i; head[i] = -1; used[i] = false;
in_du[i] = out_du[i] = 0;
}
}
char s[25];
int main()
{
int T; scanf("%d", &T);
for(int Cas=1; Cas <= T; Cas++)
{
init();
scanf("%d", &N);
for(int i=1, len, u, v, op, fu, fv; i<=N; i++)
{
scanf("%s%d", s + 1, &op);
len = (int)strlen(s + 1);
u = s[1] - 'a' + 1; v = s[len] - 'a' + 1;
used[u] = used[v] = true;
fu = fid(u); fv = fid(v);
if(fu ^ fv) root[fu] = fv;
out_du[u]++; in_du[v]++;
if(u ^ v) _add(u, v, 1);
}
printf("Case %d: ", Cas);
int root_num = 0, point_num = 0, p[3], sum = 0;
bool ok = true;
for(int i=1, x; i<=26; i++)
{
if(!used[i]) continue;
root_num += fid(i) == i;
if(root_num > 1) { ok = false; break; }
if((in_du[i] + out_du[i]) & 1)
{
p[point_num ++] = i;
if(point_num > 2) break;
}
else
{
if(in_du[i] == out_du[i]) continue;
if(out_du[i] > in_du[i])
{
x = (out_du[i] - in_du[i]) / 2;
_add(MF.S, i, x);
}
else
{
x = (in_du[i] - out_du[i]) / 2;
_add(i, MF.T, x);
}
sum += x;
}
}
if(point_num) //如果是半欧拉图的情况下,自己构建欧拉图
{
out_du[p[0]] ++; in_du[p[1]] ++;
_add(p[0], p[1], 1);
for(int i=0, x; i<2; i++)
{
if(out_du[p[i]] == in_du[p[i]]) continue;
if(out_du[p[i]] > in_du[p[i]])
{
x = (out_du[p[i]] - in_du[p[i]]) / 2;
_add(MF.S, p[i], x);
}
else
{
x = (in_du[p[i]] - out_du[p[i]]) / 2;
_add(p[i], MF.T, x);
}
sum += x;
}
}
sum >>= 1;
if(!ok || point_num > 2) { printf("Poor boy!\n"); continue; }
if(MF.max_flow() == sum) printf("Well done!\n");
else printf("Poor boy!\n");
}
return 0;
}