• 【简解】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
    ", ++op, n - tot);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    多屏共享
    md5-linux_shell
    2017年会所得
    linux无线网络配置_转
    (转)台式机华硕主板双显卡切换,怎么舒服怎么来
    Apache FtpServer 实现文件的上传和下载
    (转载)Windows 上搭建Apache FtpServer
    Eclipse常用设置
    博客园文章样式修改
    黑马公社学习
  • 原文地址:https://www.cnblogs.com/silentEAG/p/11732662.html
Copyright © 2020-2023  润新知