• HDU-2819 Swap(二分图最大匹配,路径记录)


    题意:给你一个0,1的矩阵然后你现在可以多次交换任意的两行或者两列
    使得该矩阵的对角线全为1.如果不能则输出-1
    思路:我们可以把行列交换看做一种匹配,要是得对角线的所有为1
    就要把所有的1交换到G[i][i]的位置,比如某个1在(0,1){初始行号为0}
    那么我们就可以把它交换到(0,0)或者(1,1),即交换到行号相同或者列号相同的位置
    同时题中要求的交换是得到的最终位置,而不是交换过程中的位置
    所以对于每一个行i都要进行匹配一次,就转换成了最大匹配问题
    当然记录路径我们可以是换行也可以是换列

    完整代码:

    #include <algorithm>
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    int G[105][105];
    int n;
    struct Path
    {
        int x,y;
    }path[1000];
    int match[105];
    int vis[105];
    int cnt,ans;
    bool Find(int u){
        for(int i = 1;i<=n;i++){
            if(!vis[i]&&G[u][i]){
                vis[i] = 1;
                if(!match[i]||Find(match[i])){
                    match[i] = u;//这里的match是列对行的匹配 
                    return true;
                }
            }
        }
        return false;
    }
    void printPath(){
        int tmp;
        for(int i = 1;i<=n;i++){
            if(match[i]!=i){
                for(int j =i;j<=n;j++){
                    if(match[j]==i){
                        path[cnt].x = i;
                        path[cnt++].y = j;
                        tmp = match[i];
                        match[i] = match[j];
                        match[j] = tmp;//表示列被交换
                    }
                }
            }
        }
    }
    int Count(){
        int count = 0;
        memset(match,0,sizeof(match));
        for(int i =0;i<=n;i++){
            memset(vis,0,sizeof(vis));
            if(Find(i)) count++;
        }
        return count;
    }
    int main(){
        while(cin>>n){
            for(int i = 1;i <= n; i++){
                for(int j = 1; j <= n; j++){
                    cin>>G[i][j];
                }
            }
            ans = cnt = 0;
            if(Count()!=n) cout<<-1<<endl;
            else{
                printPath();
                cout<<cnt<<endl;
                for(int i=0;i<cnt;i++){
                    printf("C %d %d
    ",path[i].x,path[i].y);
                }            
            }
        }
        return 0;
    }
  • 相关阅读:
    P3704 [SDOI2017]数字表格
    CF 700 E. Cool Slogans
    杜教筛学习笔记
    [BOI2004]Sequence 数字序列(左偏树)
    [WC2007]剪刀石头布(最大流)
    [NOI2009]变换序列(二分图匹配)
    文理分科(最小割)
    上帝与集合的正确用法(欧拉定理)
    [HAOI2008]圆上的整点(数论)
    主席树学习笔记
  • 原文地址:https://www.cnblogs.com/Tianwell/p/11338201.html
Copyright © 2020-2023  润新知