zoukankan      html  css  js  c++  java
  • [BZOJ1562/NOI2009]变换序列

    Description

    Input

    Output

    Sample Input

    5
    1 1 2 2 1

    Sample Output

    1 2 4 0 3

    HINT

    30%的数据中N≤50;
    60%的数据中N≤500;
    100%的数据中N≤10000。

    题解:  

      二分图匹配模型很显然,但是不要看到二分图就去网络流了。。。注意到题目要求的是字典序最小的!如果你用Dinic算法去多路增广,根本无法保证字典序,除非用EK。据说也有边增广边调整的搞法,但是这么多花式搞法,前提都是你不知道匈牙利算法!匈牙利算法是一种非常简单的单路增广算法,不详解了。

      这道题的重点在于你知道二分图匹配这个大专题之后怎么去求解。要求是字典序最小的解,这个很好解决。每次在插入边的时候,将字典序较大的边优先加入即可,每次优先匹配字典序较小的(因为后加入的先匹配)。

    代码:

    --------------------------------------------------------------------------------------------------

    #include <cstdio>
    #include <algorithm>
    #include <vector>
    #include <cstring>
    using namespace std;

    #define MAXN 20005
    #define INF 0x3f3f3f3f

    struct Edge { int v, next; } edge[MAXN];

    int n, d, num[MAXN], ans[MAXN], vis[MAXN], now, h[MAXN];

    void addEdge(int u, int v) { now++, edge[now] = (Edge) {v, h[u]}, h[u] = now; }

    int DFS(int o)
    {
      for (int x = h[o]; x != -1; x = edge[x].next)
      {
        int v = edge[x].v;
        if (!vis[v])
        {
          vis[v] = 1;
          if (num[v] == -1 || DFS(num[v]))
          {
            ans[o] = v, num[v] = o;
            return 1;
          }
        }
      }
      return 0;
    }

    void work()
    {
      int tot = 0;
      for (int i = n - 1; i >= 0; i--)
      {
        memset(vis, 0, sizeof(vis));
        if (DFS(i)) tot++; else break;
      }
      if (tot != n) printf("No Answer ");
      else for (int i = 0; i < n; i++) printf("%d ", ans[i]);
    }

    int x;

    int main()
    {
      freopen("transform.in", "r", stdin);
      freopen("transform.out", "w", stdout);
      memset(ans, -1, sizeof(ans)), memset(num, -1, sizeof(num)), memset(h, -1, sizeof(h));
      scanf("%d", &n);
      for (int i = 0; i <= n - 1; i++)
      {
        scanf("%d", &x);
        int v1 = i + x >= n ? (i + x) % n : i + x;
        int v2 = i - x < 0 ? i - x + n : i - x;
        if (v1 < v2) swap(v1,v2);
        addEdge(i, v1), addEdge(i, v2);
      }
      work();
      return 0;
    }

    --------------------------------------------------------------------------------------------------

  • 相关阅读:
    vue自动路由-单页面项目(非build时构建)
    建立多页面vue.js项目
    C#调用C++(QT5.5.1项目)的C++/CLI(CLR项目)项目技术笔记
    自建Socket转发,使用远程桌面(mstsc)连接家中电脑
    用Vue.js搭建一个小说阅读网站
    在CentOS中部署.Net Core2.1网站
    高价值干货:这可能是你见过最全的网络爬虫总结
    【DevCloud·敏捷智库】如何利用用户故事了解需求
    项目管理:如何显性管理并提升Story分解能力
    【API进阶之路】老板给我涨薪30%!如何通过SDK接口搞定千万级流量直播
  • 原文地址:https://www.cnblogs.com/jinkun113/p/4893387.html
Copyright © 2011-2022 走看看