题解
一道好题。
根据竞赛图性质可得,我们一定能在图中找到哈密顿路径,然后再利用竞赛图性质寻找强连通分量,并不断扩展环的大小。
我们根据推断出,每个scc(强连通分量)之间的连边必然是单向的(均为从某一scc的出边和另一scc的入边)。我们拓扑排序一下,对于每个点,先把它所在scc加入,再不断按拓扑序由大到小加入,就是答案了。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=2002,M=4e6+10;
int n,m,mp[N][N],id[N],nxt[N],in[N],pos[N];
int dfn,cnt,df[N],low[N],top,sta[N],vis[N];
vector<int>scc[N];
inline int imin(int x,int y){return x>y?y:x;}
inline bool cmp(const int& x,const int& y){return in[x]<in[y];}
inline int rd()
{
char ch=getchar();int x=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
return x*f;
}
inline void Tarjan(int x)
{
df[x]=++dfn;low[x]=df[x];sta[++top]=x;vis[x]=1;
for(int i=1;i<=n;++i) if(mp[x][i]){
if(!df[i]){
Tarjan(i);low[x]=imin(low[x],low[i]);
}else if(vis[i]) low[x]=imin(low[x],df[i]);
}
if(low[x]==df[x]){
++cnt;
for(;sta[top+1]!=x;vis[sta[top--]]=0)
scc[cnt].push_back(sta[top]),id[sta[top]]=cnt;
}
}
inline void build(int x)
{
int l=scc[x][0],r=scc[x][0],sz=scc[x].size();
for(int t,i=1;i<sz;++i){
t=scc[x][i];
if(mp[t][l]){nxt[t]=l;l=t;}
else if(mp[r][t]){nxt[r]=t;r=t;}
else{
for(int j=l;j;j=nxt[j]){
if(mp[j][t] && mp[t][nxt[j]]){
nxt[t]=nxt[j];nxt[j]=t;break;
}
}
}
}
r=0;
for(int i=nxt[l];i;i=nxt[i])
if(r){
for(int j=r,k=l;;k=j,j=nxt[j])
if(mp[i][j]){
nxt[k]=nxt[l];
if(k!=l) nxt[l]=r;
l=i;r=j;break;
}else if(j==l) break;
}else if(mp[i][l]){r=l;l=i;}
nxt[l]=r;
}
inline void insert(int x)
{
sta[++top]=x;
for(int i=nxt[x];i&& i!=x;i=nxt[i]) sta[++top]=i;
}
int main(){
int i,j;n=rd();
for(i=2;i<=n;++i)
for(j=1;j<i;++j){
mp[j][i]=rd();mp[i][j]=mp[j][i]^1;
}
for(i=1;i<=n;++i) if(!df[i]) Tarjan(i);
for(i=1;i<=cnt;++i) build(i);
for(i=2;i<=n;++i)
for(j=1;j<i;++j)
if(id[i]!=id[j]){
if(mp[i][j]) in[id[j]]++;
else if(mp[j][i]) in[id[i]]++;
}
for(i=1;i<=cnt;++i){
pos[i]=i;
in[i]/=scc[i].size();
}
sort(pos+1,pos+cnt+1,cmp);
for(i=1;i<=n;++i){
top=0;insert(i);
for(j=1;j<=cnt;++j){
if(in[pos[j]]>in[id[i]]) insert(scc[pos[j]][0]);
}
printf("%d ",top);
for(j=1;j<top;++j) printf("%d ",sta[j]);
printf("%d\n",sta[top]);
}
}