zoukankan      html  css  js  c++  java
  • UVALive 6322 最大匹配...

    /*
     *e...大概明白了。首先用最大匹配看看是不是存在符合题意的匹配。然后呢。对枚举找到每个位置符合的字母里最小的那个。
     *判断是否能构成最大匹配。直到找完最后一个位置输出就好了。、

     *还是有些不理解最大匹配匈牙利算法的过程。而且这个题是最大匹配。也没想到。
     */

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    #define N 110
    
    int g[N][N]; // 图的存储方式。矩阵。
    int n; //二分图两个顶点集 本题个数相等
    int vis[N]; //判断V2中的点是否已经被搜索过。一次寻找最大匹配中.
    int viss[N]; // 判断V2中的点是不是已经被匹配到其它位置。所有的最大匹配过程都包括。
    int link[N]; // 记录V2中的点和谁匹配了。
    int m; // 最大匹配数;
    int len; // 还未匹配的长度
    char str[N], s[N];
    int ans[N]; //保存每个位置匹配的字符对应的位置。
    
    void init()
    {
        memset(vis, 0, sizeof(vis));
        memset(viss, 0, sizeof(viss));
        memset(link, 0, sizeof(link));
        memset(g, 0, sizeof(g));
        memset(ans, 0, sizeof(ans));
        m  = 0;
    }
    
    void build()
    {
        cin >> str+1;
        n = strlen(str+1);
        sort(str+1, str+1+n);
        for (int i=1; i<=n; ++i)
        {
            cin >> s;
            int len2 = strlen(s);
            for (int j=1; j<=n; ++j)
            {
                for (int k=0; k<len2; ++k)
                {
                    if (str[j] == s[k])
                        g[i][j] = 1;  // 建图。我没想到这样建。
                }
            }
        }
    }
    
    int dfs(int x)
    {
        for (int y=1; y<=n; ++y)
        {
            if (g[x][y] && !vis[y] && !viss[y])  // 如果x和y有边。而且y未被搜索和匹配.
            {
                vis[y] = 1;  // 标记已被搜索过.
                if (link[y] == 0 || dfs(link[y]))  //如果y未被匹配。或者y匹配的节点可以找到增广路。(为什么这也算是匹配成功呢。那和这个节点匹配的怎么办)
                {
                    link[y] = x;    //当前匹配成功。
                    return 1;
                }
            }
        }
        return 0;
    }
    
    void max_m()
    {
        for (int x=1; x<=n; ++x)
        {
            memset(vis, 0, sizeof(vis)); // 清空上次搜索时的标记。
            if (dfs(x))
                m++;
        }
        return ;
    }
    
    int match()
    {
        int anss = 0;
        memset(link, 0, sizeof(link));
        for (int x=1; x<=n; ++x)
        {
            if (ans[x]) continue;
            memset(vis, 0, sizeof(vis));
            if (dfs(x)) anss++;
        }
        return anss == len;
    }
    
    int main()
    {
        int t;
        cin >> t;
        while(t--)
        {
            init();
            build();
            max_m();
            if (m  < n)
            {
                cout << "NO SOLUTION
    ";
                continue;
            }
            len = n;
            for (int i=1; i<=n; ++i) // 遍历每个位置的最小字符 用最大匹配判断是否可行。
            {
                for (int j=1; j<=n; ++j)
                {
                    if (!viss[j] && g[i][j]) // 没有被其它位置匹配。而且和当前位置有边。
                    {
                        ans[i] = j;
                        len--;
                        viss[j] = 1;
                        if (match()) break; // 当前位置成功。继续匹配下一个位置。
                        viss[j] = 0; //如果不成功。回溯。
                        len++;
                    }
                }
            }
            for (int x=1; x<=n; ++x)
            {
                cout << str[ans[x]];
            }
            cout << endl;
        }
        return 0;
    }
    LOoK
  • 相关阅读:
    数据仓库与数据挖掘的一些基本概念
    System.currentTimeMillis();
    html练习(3)
    HDU 1556 Color the ball【算法的优化】
    ubuntu12.04 安装配置jdk1.7
    java中的switch用String作为条件
    oracle中 connect by prior 递归算法
    C#复习题
    AngularJS:Http
    AngularJS:Service
  • 原文地址:https://www.cnblogs.com/icode-girl/p/4698729.html
Copyright © 2011-2022 走看看