您的位置:首页 > 其它

【图论】【二分图匹配】[HDU 2819]Swap

2015-07-28 15:24 435 查看
首先可以很容易的发现一个性质:无论怎么交换行和列,每一行每一列的元素数量始终不会改变,那么就像八皇后问题一样,只不过改成了棋盘上放了n个车不能互相冲突。那么每一个1的位置代表可以放一个车,每一个0的位置代表不能放车,那么可以发现如果在当前位置可以放个车并且放了的话,那么就不能在当前车的行和列上继续放车了,那么给行和列编号把有1的位置行和列连接起来,然后就做二分图匹配,因为是在棋盘上放车那么始终不会超过n个那么只需要看最大的匹配数量是否等于n就行了,那么方案怎么输出呢。首先可以发现如果当前可行,那么棋盘上一定放置了n个车不能互相冲突,那么肯定有n个并且每一行一个,那么只需要维护一下每一行的车的列数,然后和当前的行数比较如果不一样,就和当前行(i)的第i列交换,同时维护一下下面几行的在第i列的车改成在当前这个列就行了,然后保存下先输出次数,然后输出方案。

[code]#include <cstdio>
#include <cstring>
#include <algorithm>
//#include <conio.h>
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 400;
bool vis[MAXN+10];
int con[MAXN+10];
int endcnt;
int n, m, k, Tcnt;
struct node{ 
    int v;
    node *next;
}Edges[MAXN * MAXN * 2+10], *adj[MAXN+10], *ecnt=Edges;
void addedge(int u, int v){
    ++ecnt;
    ecnt->v = v;
    ecnt->next = adj[u];
    adj[u] = ecnt;
}
bool dfs(int u){
    for(node *p=adj[u];p;p=p->next){
        if(!vis[p->v]){
            vis[p->v] = true;
            if(con[p->v]==-1 || dfs(con[p->v])){
                con[u] = p->v;
                con[p->v] = u;
                return true;
            }
        }
    }
    return false;
}
int ys[MAXN+5];
void work(){
    int ret = 0;
    memset(con, -1, sizeof con);
    for(int i=endcnt;i>=1;i--) if(con[i] == -1){
        memset(vis, 0, sizeof vis);
        ret += dfs(i);
        //if(ret == n) break;
    }
    if(ret == n){
        vector<pair<int, int> > ans;
        int counter = 0;
        for(int i=1;i<=endcnt;i++)
            ys[i] = con[i] - n;
        for(int i=1;i<=n;i++){
            if(ys[i] != i){
                counter++;
                ans.push_back(make_pair(min(i, ys[i]), max(i, ys[i])));
                for(int j=i+1; j<=n; j++){
                    if(ys[j] == i){
                        ys[j] = ys[i];
                        break;
                    }
                }
            }
        }
        printf("%d\n", counter);
        for(int i=0;i<counter;i++)
            printf("C %d %d\n", ans[i].first, ans[i].second);
    }
    else printf("-1\n");
}
bool read(){
    int t1;
    if(scanf("%d", &n) == EOF) return false;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%d", &t1);
            if(t1){
                addedge(i, j+n);
                addedge(j+n, i);
            }
        }
    }
    endcnt=n;
    return true;
}
int main(){
    while(read()){
        work();
        memset(adj, 0, sizeof adj);
        ecnt=Edges;
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: