bzoj1059

来源:互联网 发布:软件项目考核指标 编辑:程序博客网 时间:2024/04/30 21:37

我们首先要推出几点:

一。无论怎么变换,我的1的数量不会变化

二。同一行或者同一列的1不可能经过变换然后在对角线上

基于第二点,我们得出每一列最多只能选一个,每一行最多也只能选一个。如果我们选了(i,j)那么,任何处于第i行的1或者第j列的1都不能再选

那么建图:

如果(i,j)上的是1,那么i->j连一条边,最后求一边二分图匹配,看一看是否是完美匹配。

因为当你选了i->j这条边,你就再也不能用i这个点去选边,也不能再用j这个点去选边了

#include<cstdio>#include<cstdlib>#include<cstring>char s[255];int first[205];int mat[205];bool vis[205];struct mod{int x,y,next;};mod q[50005];int len=0;void ins(int x,int y){ len++; q[len].x=x; q[len].y=y; q[len].next=first[x]; first[x]=len;}bool find(int x){ for (int i=first[x];i!=0;i=q[i].next)   {  int y=q[i].y;  if (vis[y]==true)continue;  vis[y]=true;  if (mat[y]==-1||find(mat[y])==true)  {   mat[y]=x;   return true;  } } return false;}int main(){ int ttt; scanf("%d",&ttt); while(ttt--) {  int n;  scanf("%d",&n);  memset(first,0,sizeof(first));  len=0;  for (int i=1;i<=n;i++)  {    for (int j=1;j<=n;j++)    {     int x;     scanf("%d",&x);     if (x==1)     ins(i,j);    }  }  //for (int k=1;k<=len;k++) // printf("k:%d x:%d y:%d\n",k,q[k].x,q[k].y);   int num=0;   memset(mat,-1,sizeof(mat));  for (int i=1;i<=n;i++)  {    memset(vis,false,sizeof(vis));    if (find(i)==true)num++;    else break;  }  if (num==n)printf("Yes\n");  else printf("No\n"); }     }


0 0
原创粉丝点击