• POJ 1486 Sorting Slides (二分图关键匹配边)


    题意

    给你n个幻灯片,每个幻灯片有个数字编号1~n,现在给每个幻灯片用A~Z进行编号,在该幻灯片范围内的数字都可能是该幻灯片的数字编号。问有多少个幻灯片的数字和字母确定的。

    思路

    确定幻灯片的数字就是求完美匹配也就是最大匹配,而题目要求的边就是匹配的关键边,也叫必须边,即任意一个最大匹配一定要包含这条边。 关键边求法先求一遍最大匹配,然后枚举删去匹配边,看之后的最大匹配是否减小,如果减小则该边是匹配关键边。 这让我想起了寻找关键割边:如果一个割边增加流量后整个最大流增加则该割边是关键割边。呵呵,是不是很像?算法的魅力之一就在于举一反三吧^_^~

    代码

     
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #define MID(x,y) ((x+y)/2)
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    const int MAXV = 55;                   //N1+N2
    vector  adj[MAXV];
    struct MaximumMatchingOfBipartiteGraph{
        int vn;
        void init(int n){                   //二分图两点集点的个数
            vn = n;
            for (int i = 0; i <= vn; i ++)     adj[i].clear();
        }
        void add_uedge(int u, int v){
    		adj[u].push_back(v);
    		adj[v].push_back(u);
        }
        bool vis[MAXV];
        int mat[MAXV];                      //记录已匹配点的对应点
        bool cross_path(int u){
            for (int i = 0; i < (int)adj[u].size(); i ++){
                int v = adj[u][i];
                if (!vis[v]){
                    vis[v] = true;
                    if (mat[v] == 0 || cross_path(mat[v])){
                        mat[v] = u;
                        mat[u] = v;
                        return true;
                    }
                }
            }
            return false;
        }
        int hungary(){
            mem(mat, 0);
            int match_num = 0;
            for (int i = 1; i <= vn; i ++){
                mem(vis, 0);
                if (!mat[i] && cross_path(i)){
                    match_num ++;
                }
            }
            return match_num;
        }
    }match;
    struct xy{
        int x1, x2, y1, y2;
        int x, y;
    }a[MAXV];
    bool del[MAXV][MAXV];
    void build(int n){
        match.init(n+n);
        for (int i = 1; i <= n; i ++){
            for (int j = n+1; j <= n+n; j ++){
                if (!del[i][j] && a[j].x >= a[i].x1 && a[j].x <= a[i].x2 && a[j].y >= a[i].y1 && a[j].y <= a[i].y2){
                    match.add_uedge(i, j);
                }
            }
        }
    }
    map  key_match;
    int main(){
    	//freopen("test.in", "r", stdin);
    	//freopen("test.out", "w", stdout);
    	int n;
    	int t = 1;
    	while(scanf("%d", &n), n){
            for (int i = 1; i <= n; i ++){
                scanf("%d %d %d %d", &a[i].x1, &a[i].x2, &a[i].y1, &a[i].y2);
            }
            for (int i = 1; i <= n; i ++){
                scanf("%d %d", &a[i+n].x, &a[i+n].y);
            }
            mem(del, false);
            build(n);
            int max_match = match.hungary();
            key_match.clear();
            for (int i = 1; i <= n; i ++){
                key_match.insert(make_pair(i+64, match.mat[i]-n));
            }
            map  :: iterator it;
            for (it = key_match.begin(); it != key_match.end(); it ++){
                del[it->first - 64][it->second+n] = true;
                build(n);
                del[it->first - 64][it->second+n] = false;
                int tmp_match = match.hungary();
                if (tmp_match == max_match){
                    it->second = -1;
                }
    
            }
            printf("Heap %d
    ", t ++);
            bool ok = 0;
            for (it = key_match.begin(); it != key_match.end(); it ++){
                if (it->second == -1)   continue;
                ok = 1;
                printf("(%c,%d) ", it->first, it->second);
            }
            if (ok){
                puts("
    ");
            }
            else{
                puts("none
    ");
            }
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    IOS 获取时间的问题
    JQ 点赞
    截取字符串第一个空格前的字符
    JQ 的一些方法
    匿名函数var a =function(){}和function a(){}的区别
    完美支持中文编程的 Emacs 配置文件 .emacs
    linux find 命令忽略某个或多个子目录的方法
    Linux下如何用date设置时间
    nagios的监控代码!
    shell脚本监控apache进程数和oracle连接数
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114284.html
Copyright © 2020-2023  润新知