【题解】[CCO2020] Travelling Salesperson
同步发表于我的博客 。
给定一个边权为
首先要覆盖所有点,所以路径长度不可能优于
所以我们考虑构造长度为
考虑归纳法,如果前
如果路径中所有边的颜色都相同,那么在结尾加入第
否则原路径存在一个断点
那么如果
否则我们在
所以我们只用在线支持插入,直接双向链表即可,时间复杂度
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define pre(i,a,b) for(int i=a;i>=b;i--)
#define N 2005
using namespace std;
int n,d[N][N],nxt[N],pre[N];char s[N];
inline void ins(int x,int y){nxt[y]=nxt[x];pre[y]=x;pre[nxt[x]]=y;nxt[x]=y;}
inline int g(int x){if(x==n)return 1;return x+1;}
int main(){
scanf("%d",&n);
rep(i,2,n){
scanf("%s",s+1);
rep(j,1,i-1)d[i][j]=d[j][i]=s[j]=='R';
}
rep(i,1,n){
rep(i,1,n)nxt[i]=pre[i]=0;
nxt[i]=pre[i]=g(i);pre[g(i)]=nxt[g(i)]=i;
int op=0,p=i;
for(int j=g(g(i));j!=i;j=g(j))if(j!=i){
if(!op){
if(d[pre[i]][j]!=d[i][nxt[i]])p=pre[i],op=1;
ins(pre[i],j);
}
else{
if(d[j][p]==d[p][pre[p]]){
if(d[j][nxt[p]]==d[j][p])ins(p,j),p=nxt[j];
else ins(p,j),p=j;
}
else{
if(d[j][p]==d[j][pre[p]])ins(pre[p],j),p=pre[j];
else ins(pre[p],j),p=j;
}
if(p==i||p==pre[i])op=0;
}
}
printf("%d\n%d ",n,i);int cur=nxt[i];
while(cur!=i)printf("%d ",cur),cur=nxt[cur];
putchar('\n');
}
return 0;
}