• BZOJ 1562 变换序列


    妙啊。。。。。O(N)算法。

    首先每个<n的点只连两条边。那么这就是一个环套树啊。。。。。

    然后找到在环上编号最小的点,向最小的方向更新答案。一个联通块确定了一对,就确定了这个联通块所有的样子。

    所以两遍dfs就好了。23333333orz blutrex。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 10050
    #define maxv 20050
    #define maxe 100500
    using namespace std;
    int n,d[maxn],g[maxv],nume=1,deg[maxv],ret=0,ans[maxn],dis[maxv],pre[maxv];
    int stack1[maxv],stack2[maxv],top=0;
    struct edge
    {
        int v,nxt;
    }e[maxe];
    bool vis[maxv],lab[maxv];
    void addedge(int u,int v)
    {
        e[++nume].v=v;
        e[nume].nxt=g[u];
        g[u]=nume;
    }
    void dfs1(int x,int fath)
    {
        vis[x]=true;
        for (int i=g[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (vis[v])
            {
                if (v==fath)
                {
                    if (i!=(pre[x]^1)) stack1[++top]=x,stack2[top]=v;
                    else continue;
                }
                else if (dis[v]<dis[x]) stack1[++top]=x,stack2[top]=v;
            }
            else {dis[v]=dis[x]+1;pre[v]=i;dfs1(v,x);}
        }
    }
    void dfs2(int x,int type)
    {
        vis[x]=true;
        for (int i=g[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (vis[v]) continue;
            if (!type) {ans[x]=v-n;dfs2(v,type^1);}
            else dfs2(v,type^1);
        }
    }
    int main()
    {
        scanf("%d",&n);
        for (int i=0;i<n;i++) ans[i]=-1;
        for (int i=0;i<n;i++)
        {
            scanf("%d",&d[i]);
            addedge(i,(i+d[i])%n+n);addedge((i+d[i])%n+n,i);
            addedge(i,(i-d[i]+n)%n+n);addedge((i-d[i]+n)%n+n,i);
            deg[i]+=2;deg[(i+d[i])%n+n]++;deg[(i-d[i]+n)%n+n]++;
        }
        for (int i=0;i<2*n;i++)
            if (!vis[i]) dfs1(i,-1);
        for (int i=1;i<=top;i++)
        {
            int now=stack1[i];
            while (now!=stack2[i]) 
            {
                lab[now]=true;
                now=e[pre[now]^1].v;
            }
            lab[stack2[i]]=true;
        }
        memset(vis,false,sizeof(vis));
        for (int i=0;i<n;i++)
        {
            if (!lab[i]) continue;
            if (vis[i]) continue;
            int mn=3*n;
            for (int j=g[i];j;j=e[j].nxt)
                mn=min(mn,e[j].v);
            ans[i]=mn-n;vis[i]=true;dfs2(mn,1);
        }
        for (int i=0;i<n;i++) if (ans[i]==-1) {printf("No Answer");return 0;}
        for (int i=0;i<n-1;i++) printf("%d ",ans[i]);printf("%d",ans[n-1]);
        return 0;
    }
  • 相关阅读:
    CentOs下Mongodb的下载与安装
    Mysql的sql_mode
    【Android】无限滚动的HorizontalScrollView
    Android 交错 GridView
    Android文档资源大放送 感兴趣的话可以网盘下载(个人收集)
    2014年最新720多套Android源码2.0GB免费一次性打包下载
    安卓开发之刮刮乐实例教程
    Android捕获崩溃异常
    Android -- Messager与Service
    Git的简单使用
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5919296.html
Copyright © 2020-2023  润新知