【二分图】【建图】bzoj1059 矩阵游戏

 行列作为点  行为左部 列为右部 黑色格点表示从左部向右部连边  

使左上角到右下角的连线上的格子均为黑色 一个行只能和一个列连边  相当于匹配

显然每种完美匹配对应了一个方案

并不需要考虑如何调换和调换行列后方阵是什么样的   从而降低时间复杂度

#include<cstdio>
#include<cstring>
using namespace std;
const int N=200+5;
int n,m,match[N]; bool vis[N]; 
 
int num,last[N],nxt[N*N],ver[N*N];
inline void add(int x,int y)
 {nxt[++num]=last[x]; last[x]=num; ver[num]=y;}
  
bool dfs(int x)
 {for(int i=last[x],y;i;i=nxt[i])
   {if(!vis[y=ver[i]])
     {vis[y]=1;
      if(!match[y] || dfs(match[y]))
       {match[y]=x; return 1;}
     }
   }
  return 0; 
 }
int main()
 {
 int t,r,cnt;   scanf("%d",&t);
     
 while(t--) 
  {memset(match,0,sizeof(match));   
   memset(last,0,sizeof(last)); 
   cnt=num=0;
    
   scanf("%d",&n);
   for(int i=1;i<=n;i++)
    for(int j=1;j<=n;j++)
     {scanf("%d",&r);
      if(r) add(i,j);
     }
 
   for(int i=1;i<=n;i++)
    {memset(vis,0,sizeof(vis));
     if(dfs(i)) cnt++;
     else       break;
    }
   if(cnt==n) printf("Yes\n"); 
   else       printf("No\n");
  }     
return 0;
 }

 

posted @ 2018-09-21 19:45  YuXiaoze  阅读(72)  评论(0编辑  收藏  举报