无序字母对
一道非常不错的欧拉回路(路径)题……
我们已经知道怎么求欧拉回路(路径)了,但是如果求字典序最小的呢?
求欧拉回路是一个深搜的过程……所以我们不如每次在向下一个点深搜的时候,每次让他先走那个字典序最小的节点,这样我们就能保证字典序最小了。不过实际上这个用邻接表实现会很麻烦。我的实现方法是,对于所有的边,我们先把它拆成两条有向边,对于拆出来的边赋予相同的id,之后我们把边按照起始点和终点排个序(注意邻接表的存储方法,终点要倒着排序),然后跑欧拉路径即可。
这道题中,因为我们要一个长为n+1的字符串满足n个字符对都出现过且仅出现一次,那我们就相当于是把每个字符对看成一条边,在这个图上求欧拉路径(回路),所以一开始要先判定它能否有欧拉路径(回路),之后就正常dfs。
对于起始点的选择有些神奇。我们不是每次都取最小的就行,因为如果要是求欧拉路径的话,我们必须强制选编号最小的奇点开始,如果要是求欧拉回路直接从最小的点开始即可。
这种题其实用邻接矩阵方便……而且好像这个数据范围邻接矩阵和邻接表跑的一样快。
看一下代码。
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<set> #include<queue> #define rep(i,a,n) for(int i = a;i <= n;i++) #define per(i,n,a) for(int i = n;i >= a;i--) #define enter putchar('\n') using namespace std; typedef long long ll; const int M = 20005; const int INF = 1000000009; int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') op = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { ans *= 10; ans += ch - '0'; ch = getchar(); } return ans * op; } struct edge { int next,to,from,id; bool operator < (const edge &g) const { if(from != g.from) return from < g.from; else return to > g.to; } }e[M<<1],q[M<<1]; int n,head[M],x,y,z,deg[M],ecnt = 1,minn = 100000,mpos = 100000,cnt,ans[M],tot; char s[10]; bool vis[M]; void add(int x,int y,int z) { e[++ecnt].to = y; e[ecnt].next = head[x]; e[ecnt].id = z; e[ecnt].from = x; head[x] = ecnt; } void dfs(int x) { for(int &i = head[x];i;i = e[i].next) { int k = e[i].to,j = e[i].id; if(!vis[j]) { vis[j] = 1; dfs(k); ans[++cnt] = k; } } } int main() { n = read(); rep(i,1,n) { scanf("%s",s); q[i].from = q[i+n].to = s[0] - 'A' + 1; q[i].to = q[i+n].from = s[1] - 'A' + 1; q[i].id = q[i+n].id = i; } sort(q+1,q+1+(n<<1)); rep(i,1,n<<1) { x = q[i].from,y = q[i].to,z = q[i].id; add(x,y,z),deg[x]++,deg[y]++; } //rep(i,1,100) printf("%d ",deg[i]);enter; rep(i,1,100) if((deg[i]>>1)&1) tot++; if(tot > 2) { printf("No Solution\n"); return 0; } rep(i,1,100) if(i < mpos && (deg[i]>>1) & 1) mpos = i; if(mpos == 100000) ans[++cnt] = q[1].from,dfs(q[1].from); else ans[++cnt] = mpos,dfs(mpos); if(cnt != n+1) printf("No Solution\n"); else { printf("%c",ans[1]+'A'-1); per(i,cnt,2) printf("%c",ans[i]+'A'-1); } return 0; }
当你意识到,每个上一秒都成为永恒。