zoukankan      html  css  js  c++  java
  • Swap---hdu2819(最大匹配)

    题意:通过交换行或者列来实现对角线(左上角到右下角)上都是1,

    首先,如果某行全是0或者某列全是0必然不满足情况输出-1,如果能转换的话,那么必然可以通过全由行(列)变换得到;

    还有就是对角线上的N个1,它们各自在不同的行中出现至少一次才可以,

    比如样例2中,虽然有两个1,但是它们总是处在同一列,仍然不满足要求,

    很明显不能一个行对应两个列,或者说,每一行都应该有至少一个与自己对应的列才能满足条件;

    那么将行作为X集合,列作为Y集合,如果map[i][j]==1,那么Xi->Yj连边,求最大匹配,这样的话没有任何一个行被两个列匹配,也就满足了我们的要求,

    如果最大匹配==N,那么必然有解,否则必然无解;

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<string>
    #include<stack>
    #include<map>
    using namespace std;
    #define N 1100
    #define INF 0x3f3f3f3f
    #define met(a, b) memset(a, b, sizeof(a))
    
    int used[N], G[N][N], vis[N], n;
    
    int Find(int u)
    {
        for(int i=1; i<=n; i++)
        {
            if(!vis[i] && G[u][i])
            {
                vis[i] = 1;
                if(!used[i] || Find(used[i]))
                {
                    used[i] = u;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    int main()
    {
        while(scanf("%d", &n) != EOF)
        {
            met(G, 0);
    
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=n; j++)
                {
                    int op;
                    scanf("%d", &op);
                    G[i][j] = op;
                }
            }
            int ans = 0;
            met(used, 0);
            for(int i=1; i<=n; i++)
            {
                met(vis, 0);
                ans += Find(i);
            }
            if(ans < n)
            {
                printf("-1
    ");
                continue;
            }
            int cnt = 0, a[N]={0}, b[N]={0};
    
            ///相当于是给一个数组used排序的过程,使得交换的次数最少;
            ///每次把i位置上的数,放到应该放的位置,直到当前位置是对应的数为止;
            for(int i=1; i<=n; i++)
            {
                while(i != used[i])
                {
                    a[cnt] = i;
                    b[cnt] = used[i];
                    swap(used[i],  used[used[i]]);
                    cnt ++;
                }
            }
    
            printf("%d
    ", cnt);
            for(int i=0; i<cnt; i++)
                printf("C %d %d
    ", a[i], b[i]);
        }
        return 0;
    }
    /*
    3
    0 1 1
    0 0 1
    1 0 0
    */
    View Code
  • 相关阅读:
    成为一个会思考的学习者
    我的第4篇博客
    我的第3篇博客
    第2次作业
    第一次作业:大学,人生的另一个新的开始
    第四次作业
    第三次作业
    第二次作业
    作为大一新生的感悟
    第四次作业
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/4719091.html
Copyright © 2011-2022 走看看