突然发现我现在很喜欢打图论题。
然而都是很easy的。
这道题很坑,用C++打了一遍莫名Too many or too few lines。
然后我打出了我的独门绝技Pascal。这可能是我最后一次用Pascal了。
开始讲思路。
首先每两点必须相连但无关方向,然后我们发现,可以跑一遍哈密顿回路来搞出答案。
记录与每个点相连的边。
统计一下向连边为奇数的点的个数。
0个:找一个字典序最小的点dfs
2:个:在两个奇点里找一个字典序最小的dfs
其他:无解
dfs时尽量选字典序小的,贪心即可
由于范围小就用邻接矩阵来存了(f[i,j]表示i,j有边相连,e[i]为i点的相连边数)
CODE
uses math; var e:array[0..60*60+10] of longint; f:array[0..60,0..60] of boolean; i,j,n,minn,u,v,t,tot:longint; x,y:char; ans:array[0..60*60+10] of char; procedure dfs(k:longint); var i:longint; begin for i:=0 to 60 do if f[k,i] then begin f[k,i]:=false; f[i][k]:=false; dfs(i); end; inc(tot); ans[tot]:=chr(k+ord('A')); end; begin readln(n); minn:=2147483647; for i:=1 to n do begin readln(x,y); u:=ord(x)-ord('A'); v:=ord(y)-ord('A'); minn:=min(minn,min(u,v)); f[u,v]:=true; f[v,u]:=true; inc(e[u]); inc(e[v]); end; for i:=0 to 60 do if e[i] mod 2=1 then inc(t); if t=0 then dfs(minn) else if t=2 then begin minn:=2147483647; for i:=0 to 60 do if e[i] mod 2=1 then minn:=min(minn,i); dfs(minn); end else begin writeln('No Solution'); halt; end; for i:=tot downto 1 do write(ans[i]); end.
发一把C++的,只有10分被狗了(应该是输入输出的问题)。
CODE
#include<cstdio> #include<iostream> using namespace std; const int N=205; int n,i,e[N],t,tot; bool f[N][N]; char ans[N]; void dfs(int k) { for (int i=0;i<=N;++i) if (f[k][i]) { f[k][i]=f[i][k]=0; dfs(i); } ans[++tot]=k; } int main() { //freopen("testdata.in","r",stdin); freopen("luogu.out","w",stdout); scanf("%d",&n); getchar(); for (i=1;i<=n;++i) { char x=getchar(),y=getchar(); getchar(); f[x][y]=f[y][x]=1; e[x]++; e[y]++; } for (i=0;i<=N;++i) if (e[i]%2) t++; if (t==2) { int x1,x2; for (i=0;i<=N;++i) if (e[i]%2) { x1=i; break; } for (i+=1;i<=N;++i) if (e[i]%2) { x2=i; break; } dfs(min(x1,x2)); } else if (t==0) { for (i=0;i<=N;++i) if (e[i]) break; dfs(i); } else { puts("No Solution"); return 0; } for (i=tot;i;--i) printf("%c",ans[i]); return 0; }
%%%