給出一個n個點的有向圖,任意兩個點之間有且僅一條有向邊。
對於每個點v,求出從v出發的一條經過點數最多,且沒有重複經過同一個點兩次及兩次以上的簡單路徑。
這道題首先我們要知道一個性質,一個強連通的競賽圖存在哈密頓迴路。
那麼就先tarjan一下,對每個強連通的競賽子圖處理出哈密頓迴路。然後再拓撲一下之後dp就可以了。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
vector<int>p[2010],to[2010];
queue<int>q;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();
return x*f;
}
inline void write(int x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
}
struct node
{
int x,y,next;
}a[2000010];int len,last[2010];
inline void ins(int x,int y)
{
len++;
a[len].x=x,a[len].y=y;
a[len].next=last[x],last[x]=len;
}
int id,low[2010],dfn[2010];
int top,sta[2010];
int cnt,belong[2010],rt[2010];
bool v[2010],pd[2010][2010];
inline void dfs(int x)
{
low[x]=dfn[x]=++id;sta[++top]=x,v[x]=true;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(!dfn[y])dfs(y),low[x]=min(low[x],low[y]);
else if(v[y]==true)low[x]=min(low[x],dfn[y]);
}
if(low[x]==dfn[x])
{
cnt++;rt[cnt]=x;int i;
do{
i=sta[top--];
v[i]=false;
belong[i]=cnt;p[cnt].push_back(i);
}while(i!=x);
}
}
int ru[2010],nex[2010],pre[2010],chu[2010],f[2010];
inline void solve(int x)
{
if(x==0)return ;
int y=x;
do{write(y),putchar(' ');y=nex[y];}while(y!=x);
solve(rt[pre[belong[x]]]);
}
int main()
{
//freopen("4727.in","r",stdin);
//freopen("4727.out","w",stdout);
int n=read();
for(int i=2;i<=n;i++)
{
for(int j=1;j<i;j++)
{
int id=read();
if(id==0)ins(i,j),pd[i][j]=true;
else ins(j,i),pd[j][i]=true;
}
}
for(int i=1;i<=n;i++)if(dfn[i]==0)dfs(i);
for(int i=1;i<=cnt;i++)
{
int head=p[i][0],tail=p[i][0];
for(int j=1;j<p[i].size();j++)
{
if(pd[p[i][j]][head])chu[p[i][j]]=head,head=p[i][j];
else if(pd[tail][p[i][j]])chu[tail]=p[i][j],tail=p[i][j];
else
{
int d=head;
while(1)
{
if(pd[d][p[i][j]]==true && pd[p[i][j]][chu[d]]==true){chu[p[i][j]]=chu[d],chu[d]=p[i][j];break;}
d=chu[d];
}
}
}if(p[i].size()==1){nex[tail]=head;continue;}
int u=chu[head],id;chu[tail]=0;
while(u!=0){if(pd[u][head]==true)id=u;u=chu[u];}
u=head;
while(u!=id){nex[u]=chu[u],u=chu[u];}nex[id]=head;
if(id==tail)continue;
int d=chu[id],lt=d;
while(d!=0)
{
int o=nex[head],la=head;bool bk=false;
while(o!=head)
{
if(pd[d][o]==true)
{
nex[la]=lt;bk=true;
int j=lt;
while(j!=d)nex[j]=chu[j],j=chu[j];
nex[d]=o;
break;
}
o=nex[o];la=nex[la];
}
d=chu[d];if(bk==true)lt=d;
}
}
for(int i=1;i<=len;i++)
{
int bx=belong[a[i].x],by=belong[a[i].y];
if(bx!=by)ru[bx]++,to[by].push_back(bx);
}
for(int i=1;i<=cnt;i++)if(ru[i]==0)q.push(i),f[i]=p[i].size();
while(q.empty()!=true)
{
int x=q.front();q.pop();
for(int i=0;i<to[x].size();i++)
{
int y=to[x][i],ul=f[x]+p[y].size();
if(f[y]<ul)f[y]=ul,pre[y]=x;
ru[y]--;if(ru[y]==0)q.push(y);
}
}
for(int i=1;i<=n;i++){write(f[belong[i]]),putchar(' ');solve(i),puts("");}
return 0;
}