【简解】SP7556 Stock Charts

题目大意#

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

求最少集合数。

分析#

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

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

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

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

不会?

祝好梦。

Copy
#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 @   SilentEAG  阅读(160)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示
CONTENTS