题意:给你一些单词,一些单词可以正着也可以倒着,问你给你的单词表能不能连成一单词表。
想法:由题意要想到这题不只是判断是否是欧拉回路也可以是欧拉通路,以为单词表连起来就好了,没说是要连成环还是链。不了解这个的可以看之前的博客混合欧拉图。除此以外还有最重要的一点就是图的连通性。
#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;
}