bzoj1059: [ZJOI2007]矩阵游戏(二分图匹配)

来源:互联网 发布:linux查看用户备注信息 编辑:程序博客网 时间:2024/05/16 19:27

题目传送门
好题。
让我加深了对二分图匹配的理解。

首先他让我们最后变成对角线。。
这道题我一开始在yy有什么巧妙之处。
我yy到:
如果同一列上面有两个点的话。
那么不管怎么操作也不会使得他们不在同一列。
同一行也是这个道理。
也就是说原本同一列的到最后还是同一列。
原本同一行的到最后还是同一行。
那么不同列不同行的最后也不会到同一行或者是同一列。
哦哦哦。
那这样就好办了。

最后对角线的所有点两两之间都不同行也不同列。
那么也就是一开始也都不同行或者不同列。
那么问题就转化为了在原图上求n个点使得两两之间不同行也不同列。

简单多了。
那么每一个为1的点我们把它的行跟列建立匹配关系。
然后我们去跑二分图匹配。
那么最后跑出来的结果就是不同的行匹配不同的列,那么答案不就出来了吗。
如果能完全匹配的话,此图有解。
如果不能完全匹配的话,此图无解。

#include<cstdio>#include<cstring>#include<iostream>#include<cstdlib>#include<algorithm>using namespace std;int map[210][210],n,match[210];bool chw[210];bool get_match(int x) { //匈牙利模版    for(int i=1;i<=n;i++) {        if(map[x][i]==true) {            if(chw[i]==false) {                chw[i]=true;                if(match[i]==0||get_match(match[i])==true) {                    match[i]=x;return true;                }            }        }    }    return false;}int main() {    int t;scanf("%d",&t);    while(t--) {        scanf("%d",&n);        memset(map,false,sizeof(map));        memset(match,0,sizeof(match));        for(int i=1;i<=n;i++)             for(int j=1;j<=n;j++) {                int x;scanf("%d",&x);                if(x==1) {                    map[i][j]=true; //行跟列构建关系                }            }        bool bk=true;        for(int i=1;i<=n;i++) {            memset(chw,false,sizeof(chw));            if(get_match(i)==false) {                bk=false;break;            }        }        if(bk==true) //这道题苦逼的我错了三次,就是因为Yes打成YES,哭晕在厕所[捂脸]            printf("Yes\n");        else            printf("No\n");    }    return 0;}

不错的题目。

阅读全文
0 0
原创粉丝点击