【简解】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;
}

posted @ 2019-10-24 15:51  SilentEAG  阅读(157)  评论(0编辑  收藏  举报