zoukankan      html  css  js  c++  java
  • 第十五届四川省省赛 SCU

    先给你1~N的N个数 再给你每种最多50个的条件(ai,bi,ci) 或者[ai,bi,ci]

    (ai,bi,ci)表示下标ai到bi的最小值必为ci [ai,bi,ci]表示下标ai到bi的最大值必为ci

    问你能不能有一种1~N的排列满足要求且字典序最小

    首先这是一个左边n个 右边n个的二分图 左边表示位置 右边表示值

    每个位置只能对应一个值 且要完美匹配才有解

    那么如何建边?

    我们用l[i] r[i]两个数组表示值i必定出现的最右左界和最左右界

    用minn[i] maxn[i]两个数组表示下标i这个位置所有条件里面的最大最小值和最小最大值

    这样可以使得连的边数最少.

    然后check匹配数是否为N

    在完美匹配有解的前提下完成最小字典序

    从1~N暴力依次尝试匹配比linkx小的值

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 55;
    const int N = 55;
    int l[MAXN], r[MAXN];
    int minn[MAXN], maxn[MAXN];
    int n;
    int useif[N];   //记录y中节点是否使用 0表示没有访问过,1为访问过
    int linky[N];   //记录当前与y节点相连的x的节点
    int linkx[N];
    int mat[N][N]; //记录连接x和y的边,如果i和j之间有边则为1,否则为0
    int gn, gm;   //二分图中x和y中点的数目
    int can(int t)
    {
        int i;
        for (i = 1; i <= gm; i++) {
            if (useif[i] == 0 && mat[t][i]) {
                useif[i] = 1;
                if (linky[i] == -1 || can(linky[i])) {
                    linky[i] = t;
                    linkx[t] = i;
                    return 1;
                }
            }
        }
        return 0;
    }
    int MaxMatch()
    {
        int i, num;
        num = 0;
        memset(linky, -1, sizeof(linky));
        memset(linkx, -1, sizeof(linkx));
        for (i = 1; i <= gn; i++) {
            memset(useif, 0, sizeof(useif));
            if (can(i)) {
                num++;
            }
        }
        return num;
    }
    void init()
    {
        memset(mat, 0, sizeof(mat));
        for (int i = 1; i <= n; i++) {
            minn[i] = l[i] = 1, maxn[i] = r[i] = n;
        }
    }
    int main()
    {
        int m1, m2;
        while (scanf("%d %d %d", &n, &m1, &m2) != -1) {
            init();
            int u, v, c;
            gn = gm = n;
            for (int i = 1; i <= m1; i++) {
                scanf("%d %d %d", &u, &v, &c);
                for (int j = u; j <= v; j++) {
                    minn[j] = max(minn[j], c);
                }
                l[c] = max(l[c], u);
                r[c] = min(r[c], v);
            }
            for (int i = 1; i <= m2; i++) {
                scanf("%d %d %d", &u, &v, &c);
                for (int j = u; j <= v; j++) {
                    maxn[j] = min(maxn[j], c);
                }
                l[c] = max(l[c], u);
                r[c] = min(r[c], v);
            }
            for (int i = 1; i <= n; i++) {
                for (int j = minn[i]; j <= maxn[i]; j++) {
                    if (l[j] <= i && i <= r[j]) {
                        mat[i][j] = 1;
                    }
                }
            }
            int ans = MaxMatch();
            if (ans != n) {
                printf("-1
    ");
            } else {
                for (int i = 1; i <= n; i++) {
                    int now = linkx[i];
                    mat[i][now] = 0;
                    linky[now] = -1;
                    bool flag = 0;
                    memset(useif, 0, sizeof(useif));
                    for (int j = 1; j < now; j++) {
                        if (useif[j] == 0 && mat[i][j]) {
                            useif[j] = 1;
                            if (linky[j] == -1 || can(linky[j])) {
                                linky[j] = i;
                                linkx[i] = j;
                                flag = 1;
                                break;
                            }
                        }
                    }
                    if (!flag) {
                        mat[i][now] = 1;
                        linky[now] = i;
                        linkx[i] = now;
                    }
                    now = linkx[i];
                    for (int j = 1; j <= n; j++) {
                        mat[j][now] = 0;
                    }
                }
                for (int i = 1; i <= n; i++) {
                    printf("%d", linkx[i]);
                    if (i != n) {
                        printf(" ");
                    } else {
                        printf("
    ");
                    }
                }
            }
        }
    }
    View Code
  • 相关阅读:
    NPM 使用介绍
    tight
    c# 选择排序
    AssetBundle Manager and Example Scenes
    非常棒的轨迹插件Better Trails v1.4.6
    【模型】Toon Dragon
    unity实现3D物体上的事件监听处理
    Alley Bird 跳跳鸟源码
    Unity性能优化 – 脚本篇
    欧拉角与万向节死锁
  • 原文地址:https://www.cnblogs.com/Aragaki/p/9917273.html
Copyright © 2011-2022 走看看