zoukankan      html  css  js  c++  java
  • bzoj千题计划232:bzoj4727: [POI2017]Turysta

    http://www.lydsy.com/JudgeOnline/problem.php?id=4727

    竞赛图tarjan缩点后得到的拓扑图一定是一条链

    因为竞赛图任意两点的前后顺序确定,只有一种拓扑序列

    竞赛图tarjan缩完点后,若出现强联通分量A和B

    那么A中所有点 和 B中所有点的连边 要么全指向A中所有点,要么全指向B中所有点

    否则A和B就是一个强联通分量

    所以把缩完点之后按点的入度从小到大排序,即可得到竞赛图的拓扑序列

    在这个拓扑序列上,可以从前面的强联通分量中任意一个点出来,到达后面的强联通分量的任意一个点

    因为竞赛图的任意强联通子图存在一条哈密顿回路

    那么再求出每个强联通分量的哈密顿回路

    枚举起点,先把起点所在的哈密顿回路扔进栈,然后再按拓扑序把后面的哈密顿回路扔进栈,输出即可

    如何在竞赛图哈密顿路径的基础上构造回路,详请参见博客http://www.cnblogs.com/TheRoadToTheGold/p/8439160.html

    #include<cstdio>
    #include<vector>
    #include<iostream>
    #include<algorithm>
    
    using namespace std;
    
    #define N 2001
    
    int n;
    bool mp[N][N];
    
    int tot;
    int dfn[N],low[N];
    int st[N],top;
    bool vis[N];
    
    int cnt;
    int id[N];
    vector<int>scc[N];
    
    int nxt[N];
    
    int pos[N],in[N];
    
    template<typename T>
    void read(T &x)
    {
        x=0; char c=getchar();
        while(!isdigit(c)) c=getchar();
        while(isdigit(c)) { x=x*10+c-'0'; c=getchar(); }
    }
    
    void tarjan(int x)
    {
        dfn[x]=low[x]=++tot;
        st[++top]=x;
        vis[x]=true;
        for(int i=1;i<=n;++i)    
        {
            if(!mp[x][i]) continue;
            if(!dfn[i]) 
            {
                tarjan(i);
                low[x]=min(low[x],low[i]);
            }
            else if(vis[i]) low[x]=min(low[x],dfn[i]);
        }
        if(low[x]==dfn[x])
        {
            cnt++;
            while(st[top]!=x)
            {
                scc[cnt].push_back(st[top]);
                id[st[top]]=cnt;
                vis[st[top--]]=false;
            }
            scc[cnt].push_back(x);
            id[x]=cnt;
            vis[x]=false;
            top--;
        }
    }
    
    bool cmp(int a,int b)
    {
        return in[a]<in[b];
    }
    
    void insert(int x)
    {
        st[++top]=x;
        for(int i=nxt[x];i && i!=x;i=nxt[i]) st[++top]=i;
    }
    
    int main()
    {
        read(n);
        for(int i=1;i<n;++i)
            for(int j=1;j<=i;++j)
            {
                read(mp[j][i+1]);
                mp[i+1][j]=mp[j][i+1]^1;
            }
        for(int i=1;i<=n;++i)
            if(!dfn[i]) tarjan(i);
        for(int now=1;now<=cnt;++now)
        {
            int siz=scc[now].size();
            int l,r;
            l=r=scc[now][0];
            for(int i=1,t;i<siz;++i)
            {
                t=scc[now][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;
                        }
                        if(j==l) break;
                    }
                }
                else if(mp[i][l]) r=l,l=i;
            nxt[l]=r;
        }
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j)
                if(id[i]!=id[j] && mp[i][j])
                    in[id[j]]++;
        for(int i=1;i<=cnt;++i)
        {
            pos[i]=i;
            in[i]/=scc[i].size();
        }
        sort(pos+1,pos+cnt+1,cmp);
        for(int i=1;i<=n;++i)
        {
            top=0; insert(i);
            for(int j=1,t;j<=cnt;++j)
                if(in[t=pos[j]]>in[id[i]])
                    insert(scc[t][0]);
            printf("%d ",top);
            for(int j=1;j<=top;++j)    
            {
                printf("%d",st[j]);
                putchar(j==top ? '
    ' : ' ');
            }
        }
    }    
  • 相关阅读:
    PID控制心得 2013/2/11
    在LaTeX文档中插入图片的几种常用的方法
    学习总结 2013/2/11
    eclipse 中引用其他项目及项目打包
    随笔2013/2/13
    随笔2013/2/19
    【转载】Latex对中文的支持 模版
    Latex 第二个程序
    Fences 桌面图标整理收纳箱
    消除“星期一综合症” 大前研一的周末时间分配术
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/8440943.html
Copyright © 2011-2022 走看看