首先竞赛图保证是一定有哈密顿路径的,强连通的竞赛图一定有哈密顿回路
竞赛图求每个点的最长链,不重复经过点
思路就是对每个scc求出哈密顿回路,再按拓扑序n^2dp一下
哈密顿路径和哈密顿回路的构造法看的这篇文章Bfk_
#include<bits/stdc++.h>
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<iostream>
#include<math.h>
#include<stack>
#include<set>
#include<map>
#include<vector>
#include<iomanip>
#include<bitset>
using namespace std; //
#define ll long long
#define ull unsigned long long
#define pb push_back
#define FOR(a) for(int i=1;i<=a;i++)
#define sqr(a) (a)*(a)
#define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y))
ll qp(ll a,ll b,ll mod){
ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t;
}
struct DOT{ll x;ll y;};
//inline void read(int &x){int k=0;char f=1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=-1;for(;isdigit(c);c=getchar())k=k*10+c-'0';x=k*f;}
const int dx[4]={0,0,-1,1};
const int dy[4]={1,-1,0,0};
const int inf=0x3f3f3f3f;
const ll Linf=0x3f3f3f3f3f3f3f3f;
const ll mod=1e9+7;;
const int maxn=2e3+43;
int n,g[maxn][maxn];
int dfn[maxn],low[maxn],Time,S[maxn],ins[maxn],top,belong[maxn];
int cnt,root[maxn]; //scc数量,scc至高点
int tot,V[maxn];//scc.size
int nxt[maxn];
int pre[maxn],to[maxn][maxn],du[maxn];
int q[maxn];
int dp[maxn];
void get(){ //scc内路径
//造哈密顿路径
int head=V[1];int tail=V[1];
if(tot==1){nxt[tail]=tail;return;}
for(int j=2;j<=tot;j++){
int i=V[j];
if(g[i][head]){nxt[i]=head;head=i;continue;}
else if(g[tail][i]){nxt[tail]=i;tail=i;continue;}
int x,y;
for(x=nxt[head],y=head;x&&!g[i][x];y=x,x=nxt[x]);
nxt[y]=i;nxt[i]=x;
}
//造哈密顿回路
tail=head;head=0;
for(int i=nxt[tail];i;i=nxt[i]){
if(head){
for(int p1=head,p2=tail;;p2=p1,p1=nxt[p1]){
if(g[i][p1]){
nxt[p2]=nxt[tail];
if(p2!=tail)nxt[tail]=head;
tail=i;head=p1;break;
}
if(p1==tail)break;
}
}
else if(g[i][tail]){head=tail;tail=i;}
}
nxt[tail]=head;
}
void dfs(int u){
Time++;dfn[u]=low[u]=Time;
ins[u]=1;S[++top]=u;
for(int v=1;v<=n;v++)if(g[u][v]){
if(!dfn[v]){dfs(v);low[u]=min(low[u],low[v]);}
else if(ins[v])low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u]){
cnt++;root[cnt]=u;tot=0;
while(1){
dp[cnt]++;V[++tot]=S[top];
belong[S[top]]=cnt;ins[S[top]]=0;
top--;if(S[top+1]==u)break;
}
get();
}
}
void print(int x){
if(!x){printf("\n");return;}
printf("%d ",x);
for(int i=nxt[x];i!=x;i=nxt[i])printf("%d ",i);
print(root[pre[belong[x]]]);
}
int main(){
scanf("%d",&n);
for(int i=1;i<n;i++)for(int j=1;j<=i;j++){
int x;scanf("%d",&x);
if(x)g[j][i+1]=1;
else g[i+1][j]=1;
}
for(int i=1;i<=n;i++)if(!dfn[i])dfs(i);
for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){
if(g[i][j] && belong[i]!=belong[j])to[belong[i]][belong[j]]=1;
}
for(int i=1;i<=cnt;i++){
for(int j=1;j<=cnt;j++){
if(i!=j&&to[j][i])du[i]++;
}
}
int lf=1,rg=0;top=0;
for(int i=1;i<=cnt;i++)if(du[i]==0)S[++rg]=i; //无入度
while(lf<=rg){
int x=q[++top]=S[lf];lf++; //压入q栈从叶子dp
for(int y=1;y<=cnt;y++){
if(!to[x][y]||y==x)continue;
du[y]--;if(du[y]==0)S[++rg]=y;
}
}
for(int i=top;i>=1;i--){
int x=q[i];int det=0;
for(int y=1;y<=cnt;y++){
if(!to[x][y]||x==y)continue;
if(det<dp[y]){det=dp[y];pre[x]=y;}
}
dp[x]+=det;
}
for(int i=1;i<=n;i++){
printf("%d ",dp[belong[i]]);
print(i);
}
}