[bzoj1059]矩阵游戏
二分图匹配经典题。。
因为每一行的点不管如何交换也不会不在同一行,同理,同一列的点无论如何交换都仍然在这一列。
那么也就是说要选则一些点使得满足题意,那么就可以去跑匹配了。
若A[i][j]是黑色的,那么就从i行向j列连边,最后跑匹配。
(如果用边表的话一定要记得清空计数器。。。不然就炸了。。)

1 #include <iostream> 2 #include <algorithm> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cstdio> 6 #include <queue> 7 8 using namespace std; 9 10 const int N=201000; 11 int h[600],r[N],to[N],flow[N],d[N],cur[N],v[600],tot,S,T; 12 queue<int>q; 13 14 inline void ins2(int u,int v,int f){ 15 to[tot]=v,flow[tot]=f,r[tot]=h[u]; 16 h[u]=tot++; 17 } 18 19 inline void ins(int u,int v,int f){ 20 ins2(u,v,f); 21 ins2(v,u,0); 22 } 23 24 inline bool BFS(){ 25 for(int i=S;i<=T;i++)v[i]=0,d[i]=-1; 26 d[S]=0,v[S]=1,q.push(S); 27 while(q.size()){ 28 int f=q.front();q.pop(); 29 for(int i=h[f];i!=-1;i=r[i]){ 30 int t=to[i]; 31 if(flow[i]&&!v[t]){ 32 d[t]=d[f]+1; 33 v[t]=1; 34 q.push(t); 35 } 36 } 37 } 38 return v[T]; 39 } 40 41 int DFS(int x,int f){ 42 if(x==T||!f)return f; 43 int ret=0,ff; 44 for(int &i=cur[x];i!=-1;i=r[i]){ 45 int t=to[i]; 46 if(d[t]==d[x]+1&&(ff=DFS(t,min(flow[i],f)))>0){ 47 flow[i]-=ff,flow[i^1]+=ff,ret+=ff; 48 f-=ff; 49 if(!f)break; 50 } 51 } 52 return ret; 53 } 54 55 int mf(){ 56 int f=0; 57 while(BFS()){ 58 for(int i=S;i<=T;i++)cur[i]=h[i]; 59 f+=DFS(S,0x3f3f3f3f); 60 } 61 return f; 62 } 63 64 int main(){ 65 int tt;scanf("%d",&tt); 66 while(tt--){ 67 tot=0; 68 memset(h,-1,sizeof(h)); 69 int n,x; 70 scanf("%d",&n); 71 S=0,T=n<<1|1; 72 for(int i=1;i<=n;i++) 73 for(int j=1;j<=n;j++){ 74 scanf("%d",&x); 75 if(x)ins(i,n+j,1); 76 } 77 for(int i=1;i<=n;i++)ins(S,i,1),ins(n+i,T,1); 78 puts(mf()==n?"Yes":"No"); 79 } 80 }