【简解】SP7556 Stock Charts

题目大意

给出一个折线图,有N条线段,你想要把这些线段分成几个集合,使得每个集合中任意两条线段不相交。

求最少集合数。

分析

喵帕斯:以下提及的所有折线均指横坐标在\([1,k]\)里的折线段。

思考两个折线若不相交会是什么情况?

对,即一个在上,一个在下(怎么有点奇怪呢)。

比如折线\(a\)在上,折线\(b\)在下,尝试对所有满足此关系的折线二元组连一条\(a\)\(b\)的有向边,我们可以发现,使用一个集合可以走一条路径,那么题目求最小集合数,即求走最少的路径,师所有点全部被覆盖。
然后此题就转化为了最小路径覆盖问题,假设你已经会了该问题,然后就是喜闻乐见的匈牙利模板时间啦~

不会?

祝好梦。

#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
const int N = 200 + 5;
const int M = 10000 + 5;

inline int read(){
    int f = 1, x = 0; char ch;
    do { ch = getchar(); if (ch == '-') f = -1; } while (ch < '0' || ch > '9');
    do {x = (x << 3) + (x << 1) + ch - '0'; ch = getchar(); } while (ch >= '0' && ch <= '9'); 
    return f * x;
}

inline void write(int x) {
    if (x < 0) putchar('-'), x = -x;
    if (x > 9) write(x / 10);
    putchar(x % 10 + '0');
}

inline int max(int a, int b) { return a < b ? b : a; }

inline int min(int a, int b) { return a < b ? a : b; }

struct Graph {
    int to[M << 1], nxt[M << 1], head[N], cnt;
    inline void add(int x, int y) {
        ++cnt;
        to[cnt] = y, nxt[cnt] = head[x], head[x] = cnt;
        return;
    }
}G;
int t, n, k, price[N][30], op, tot;
int vis[N], match[N], bj[N];
inline bool dfs(int u) {
    for (int i = G.head[u];i;i = G.nxt[i]) {
        int v = G.to[i];
        if (!vis[v]) {
            vis[v] = 1;
            if (!match[v] || dfs(match[v])) {
                match[v] = u, bj[u] = v;
                return 1;
            }
        }
    }
    return 0;
}

int rate[N];
inline bool cmp(const int &x, const int &y) {
    return price[x][0] > price[y][0];
}

inline bool can(int u, int v) {
    for (int i = 1;i <= k; ++i) {
        if (price[u][i] <= price[v][i]) return 0;
    }
    return 1;
}

int main(){
//  freopen("in.txt", "r", stdin);
//  freopen("out.txt", "w", stdout);
    t = read();
    while (t --) {
        n = read(), k = read();
        memset(bj, 0, sizeof bj);
        memset(G.head, 0, sizeof G.head);
        memset(match, 0, sizeof match);
        memset(price, 0, sizeof price);
        G.cnt = 0;
        for (int i = 1;i <= n; ++i) {
            for (int j = 1;j <= k; ++j) {
                price[i][j] = read();
                price[i][0] = max(price[i][0], price[i][j]);
            }
            rate[i] = i;
        }

        std :: sort(rate + 1, rate + 1 + n, cmp);

        for (int i = 1, u;i <= n; ++i) {
            u = rate[i];
            for (int j = i + 1, v;j <= n; ++j) {
                v = rate[j];
                if (can(u, v)) G.add(u, v);
            }
        }

        tot = 0;
        for (int i = 1;i <= n; ++i) {
            if (bj[i] == 0) {
                memset(vis, 0, sizeof vis);
                if (dfs(i)) tot ++;
            }
        }
        printf("Case #%d: %d\n", ++op, n - tot);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/silentEAG/p/11732662.html