3 6 aloha 0 arachnid 0 dog 0 gopher 0 tar 1 tiger 0 3 thee 1 earn 0 nothing 0 2 pat 1 acm 0
Case 1: Well done! Case 2: Well done! Case 3: Poor boy!HintIn the first case, the word “tar” is still meaningful when reversed, and love8909 can make a list as “aloha-arachnid-dog-gopher-rat-tiger”. In the second case, the word “thee” is still meaningful when reversed, and love8909 can make a list as “thee-earn-nothing”. In the third case, no lists can be created.
题意:给出n个单词,问这些单词能否首尾相连组成一个整体,其中部分单词可以翻转。
思路:将每个单词的首尾字母看成结点,每个单词看成一条边,可以看出这是一张混合图,要求判断是否有欧拉路。使用判断欧来回路的方法,如果存在欧拉回路那么就一定存在欧拉路了;否则如果有且仅有两个点的(出度-入度)是奇数,那么给这两个点加边,判断是否存在欧拉回路。注意这一题要判断图的连通性。
代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #pragma comment (linker,"/STACK:102400000,102400000") #define maxn 30 #define MAXN 2005 #define mod 1000000009 #define INF 0x3f3f3f3f #define pi acos(-1.0) #define eps 1e-6 #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define FRE(i,a,b) for(i = a; i <= b; i++) #define FREE(i,a,b) for(i = a; i >= b; i--) #define FRL(i,a,b) for(i = a; i < b; i++) #define FRLL(i,a,b) for(i = a; i > b; i--) #define mem(t, v) memset ((t) , v, sizeof(t)) #define sf(n) scanf("%d", &n) #define sff(a,b) scanf("%d %d", &a, &b) #define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c) #define pf printf #define DBG pf("Hi\n") const int MAXM = 30000; typedef long long ll; using namespace std; struct Edge { int to,next,cap,flow; }edge[MAXM]; int st,ed; int d[MAXN]; int tol,m,s; int head[MAXN]; int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN]; int in[MAXN],out[MAXN]; void init() { tol=0; memset(head,-1,sizeof(head)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); } //加边,单向图三个参数,双向图四个参数 void addedge(int u,int v,int w,int rw=0) { edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u]; edge[tol].flow=0; head[u]=tol++; edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v]; edge[tol].flow=0; head[v]=tol++; } //输入参数:起点,终点,点的总数 //点的编号没有影响,只要输入点的总数 int sap(int start,int end,int N) { memset(gap,0,sizeof(gap)); memset(dep,0,sizeof(dep)); memcpy(cur,head,sizeof(head)); int u=start; pre[u]=-1; gap[0]=N; int ans=0; while (dep[start]<N) { if (u==end) { int Min=INF; for (int i=pre[u];i!=-1;i=pre[edge[i^1].to]) if (Min>edge[i].cap-edge[i].flow) Min=edge[i].cap-edge[i].flow; for (int i=pre[u];i!=-1;i=pre[edge[i^1].to]) { edge[i].flow+=Min; edge[i^1].flow-=Min; } u=start; ans+=Min; continue; } bool flag=false; int v; for (int i=cur[u];i!=-1;i=edge[i].next) { v=edge[i].to; if (edge[i].cap-edge[i].flow && dep[v]+1==dep[u]) { flag=true; cur[u]=pre[v]=i; break; } } if (flag) { u=v; continue; } int Min=N; for (int i=head[u];i!=-1;i=edge[i].next) if (edge[i].cap-edge[i].flow && dep[edge[i].to]<Min) { Min=dep[edge[i].to]; cur[u]=i; } gap[dep[u]]--; if (!gap[dep[u]]) return ans; dep[u]=Min+1; gap[dep[u]]++; if (u!=start) u=edge[pre[u]^1].to; } return ans; } int father[MAXN]; int find_father(int x) { if (x!=father[x]) father[x]=find_father(father[x]); return father[x]; } void Union(int a,int b) { int fa=find_father(a); int fb=find_father(b); if (fa!=fb) father[fa]=fb; } int main() { // freopen("C:/Users/asus1/Desktop/IN.txt","r",stdin); int i,j,t,n,d,cas=1,x; char str[30]; scanf("%d",&t); while (t--) { init(); for (i=0;i<30;i++) father[i]=i; scanf("%d",&n); for (i=0;i<n;i++) { scanf("%s %d",str,&d); int len=strlen(str); out[str[0]-'a']++; in[str[len-1]-'a']++; x=str[0]-'a'; if (d==1) addedge(str[0]-'a',str[len-1]-'a',1); Union(str[0]-'a',str[len-1]-'a'); } int cnt=0; int w[30]; bool flag=true; for (i=0;i<26;i++) { if (in[i]||out[i]) { if (find_father(i)!=find_father(x)) { flag=false; break; } if ((out[i]-in[i])%2) w[cnt++]=i; } } if (cnt!=0&&cnt!=2||!flag) { printf("Case %d: Poor boy!\n",cas++); continue; } if (cnt==2) { in[w[0]]++; out[w[1]]++; addedge(w[0],w[1],1); } sap(26,27,28); for (i=head[26];i+1;i=edge[i].next) { if (edge[i].cap>0&&edge[i].cap>edge[i].flow) { flag=false; break; } } if (flag) printf("Case %d: Well done!\n",cas++); else printf("Case %d: Poor boy!\n",cas++); } return 0; }
原文地址:http://blog.csdn.net/u014422052/article/details/45677353