bzoj 4727 [POI2017]Turysta 竞赛图

来源:互联网 发布:跳跃网络被告 编辑:程序博客网 时间:2024/06/05 17:09

对于一个竞赛图:
一定存在哈密顿路径
如果强连通,一定存在哈密顿回路
tarjan缩点后得到的拓扑图是一条有向链,上方的点向下方的点连边。

#include <bits/stdc++.h>using namespace std;#define N 2100int n,top,scc,cnt;int mp[N][N],dfn[N],low[N],st[N],ins[N],bel[N];int nex[N],ru[N],pos[N],size[N];vector<int>vec[N];int read(){    char ch=getchar();int ret=0;    for(;ch<'0'||ch>'9';ch=getchar());    for(;ch>='0'&&ch<='9';ch=getchar())        ret=ret*10+ch-'0';    return ret;}void print(int x){    if(x>=10)print(x/10);    putchar(x%10+'0');}void tarjan(int x){    st[++top]=x;ins[x]=1;    low[x]=dfn[x]=++cnt;    for(int i=1;i<=n;i++)if(mp[x][i])    {        if(!dfn[i])            tarjan(i),low[x]=min(low[x],low[i]);        else if(ins[i])            low[x]=min(low[x],dfn[i]);    }    if(dfn[x]==low[x])    {        int tmp=st[top--];        bel[tmp]=++scc;ins[tmp]=0;        vec[scc].push_back(tmp);size[scc]++;        while(tmp!=x)        {            tmp=st[top--];            bel[tmp]=scc;ins[tmp]=0;            vec[scc].push_back(tmp);size[scc]++;        }    }}int cmp(int x,int y){return ru[x]<ru[y];}void insert(int x){    st[++top]=x;    for(int i=nex[x];i&&i!=x;i=nex[i])        st[++top]=i;}int main(){    n=read();    for(int i=2;i<=n;i++)        for(int j=1;j<i;j++)        {            mp[j][i]=read();            mp[i][j]=mp[j][i]^1;        }    for(int i=1;i<=n;i++)if(!dfn[i])        tarjan(i);    for(int now=1;now<=scc;now++)    {        cnt=vec[now].size();        int h,r;h=r=vec[now][0];        for(int i=1,t;i<cnt;i++)        {            t=vec[now][i];            if(mp[t][h])nex[t]=h,h=t;            else if(mp[r][t])nex[r]=t,r=t;            else            {                for(int j=h;;j=nex[j])                    if(mp[j][t]&&mp[t][nex[j]])                    {                        nex[t]=nex[j];nex[j]=t;                        break;                    }            }        }        r=0;        for(int i=nex[h];i;i=nex[i])        {            if(r)            {                   for(int j=r,k=h;;k=j,j=nex[j])                {                    if(mp[i][j])                    {                        nex[k]=nex[h];                        if(k!=h)nex[h]=r;                        h=i;r=j;break;                    }                    if(j==h)break;                }            }            else if(mp[i][h])r=h,h=i;        }        nex[h]=r;    }    for(int i=1;i<=n;i++)        for(int j=1;j<=n;j++)            if(bel[i]!=bel[j]&&mp[i][j])                ru[bel[j]]++;    for(int i=1;i<=scc;i++)        pos[i]=i,ru[i]/=size[i];    sort(pos+1,pos+1+scc,cmp);    for(int i=1;i<=n;i++)    {        top=0;insert(i);        for(int j=1,t;j<=scc;j++)            if(ru[t=pos[j]]>ru[bel[i]])                insert(vec[t][0]);        printf("%d ",top);        for(int j=1;j<=top;j++)            print(st[j]),putchar(j==top ? '\n':' ');    }    return 0;}
0 0
原创粉丝点击