ZJOI2007矩阵游戏

图论专题里的东西,二分图呗,然而不知道怎么建图……

就直接是1就连当前行和当前列,大样例都没试,直接交,ZJOI题能这么简单?50?数据这么水,瞎打都有50。上个厕所。

回来跟Wxy吐槽数据水,他说你咋做的,我说二分图啊,他说对呀,就是二分图,我说恩?怎么建的图,然后让他点开看看,他说对呀,就这么建图。

当时异常无语,这就把正解搞出来了?回去把前向星一清空就A了……

目标状态,就是让你用n个棋子占领所有行和列,手模的时候可以发现,只要这两棋子在一行(列)了,就没有办法把他们换成两行(列)。所以棋子还是很像二分图的边的。

那就直接求最大匹配看看是不是n就完事了,n略小,来一手匈牙利。

当然你要是用dinic求的话我也没什么意见(等我学了着,哼~)。

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<map>
using namespace std;
struct EDGE{
    int ed,nex;
}edge[100000];int first[600],num;
int read(){
    int sum=0,f=1;char x=getchar();
    while(x<'0'||x>'9'){
        if(x=='-') f=-1;
        x=getchar();
    }while(x>='0'&&x<='9'){
        sum=sum*10+x-'0';
        x=getchar();
    }return sum*f;
}
int T,n;
int a[250][250],match[600],ans;
bool visit[600];
void add(int st,int ed){
    edge[++num].ed=ed;
    edge[num].nex=first[st];
    first[st]=num;
}
bool dfs(int x){
    for(int i=first[x];i;i=edge[i].nex){
        int y=edge[i].ed;
        if(!visit[y]){
            visit[y]=1;
            if(!match[y]||dfs(match[y])){
                match[y]=x;
                return true;
            }
        }
    }return false;
}
int main(){
    /*freopen("2.in","r",stdin);
    freopen("2.out","w",stdout);*/
    T=read();
    while(T--){
        n=read();ans=0;num=0;
        memset(edge,0,sizeof(edge));
        memset(match,0,sizeof(match));
        memset(first,0,sizeof(first));
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                a[i][j]=read();
                if(a[i][j]) add(i,j);
            }
        for(int i=1;i<=n;i++){
            memset(visit,0,sizeof(visit));
            if(dfs(i)) ans++;
        }
        if(ans>=n)puts("Yes");
        else puts("No");
    }return 0;
}
View Code
原文地址:https://www.cnblogs.com/Yu-shi/p/11172163.html