zoukankan      html  css  js  c++  java
  • bzoj1059[ZJOI2007] 矩阵游戏

    题目链接:bzoj1059

    题目大意:

    给一个N*N的矩阵,上面有黑白两种颜色的格子。每次可以对该矩阵进行两种操作:行交换操作:选择矩阵的任意两行,交换这两行(即交换对应格子的颜色)列交换操作:选择矩阵的任意行列,交换这两列(即交换对应格子的颜色)游戏的目标,即通过若干次操作,使得方阵的主对角线(左上角到右下角的连线)上的格子均为黑色。问有没有方案能实现。


    题解:

    二分图最大匹配

    因为由题意(%hyc)可以发现,实际上是求有没有n个行列互不相同的棋子。于是把行跟列当二分图连边(有点像网络流的经典模型),x行y列有个黑棋子就连x->y。跑个二分图最大匹配就好了。
    然而我一直在往求最大点独立集那方面想..而时间复杂度也根本不允许我建图...

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    #define maxn 41000
    
    struct node
    {
    	int x,y,next;
    }a[maxn*2];int len,first[maxn];
    int n,bf[maxn],ask[maxn],tim;
    void ins(int x,int y)
    {
    	++len;
    	a[len].x=x;a[len].y=y;
    	a[len].next=first[x];first[x]=len;
    }
    int ffind(int x)
    {
    	for (int i=first[x];i!=-1;i=a[i].next)
    	 if (ask[a[i].y]!=tim)
    	 {
    		 int y=a[i].y;
    		 ask[y]=tim;
    		 if (bf[y]==-1 || ffind(bf[y]))
    		 {
    			 bf[y]=x;
    			 return true;
    		 }
    	 }
    	return false;
    }
    bool xyl()
    {
    	memset(ask,0,sizeof(ask));
    	memset(bf,-1,sizeof(bf));
    	for (int i=1;i<=n;i++)
    	{
    		tim++;
    		if (!ffind(i)) return false;
    	}
    	return true;
    }
    int main()
    {
    	int T,i,j,x;
    	scanf("%d",&T);
    	while (T--)
    	{
    		len=tim=0;
    		memset(first,-1,sizeof(first));
    		scanf("%d",&n);
    		for (i=1;i<=n;i++)
    	  	 for (j=1;j<=n;j++)
    		 {
    			scanf("%d",&x);
    			if (x==1) ins(i,j);
    		 }
    		if (xyl()) printf("Yes
    ");
    		else printf("No
    ");
    	}
    	return 0;
    }


  • 相关阅读:
    Java基础——银行例题
    JavaEE——HTML5绘画
    Java基础——构造器
    HTML5-GPS定位
    HTML+CSS+JavaScript小例题
    JDBC综合例题
    java并发编程(更新)
    struts2配置文件的解释
    排序
    集合
  • 原文地址:https://www.cnblogs.com/Euryale-Rose/p/6527801.html
Copyright © 2011-2022 走看看