图论专题里的东西,二分图呗,然而不知道怎么建图……
就直接是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; }