1. 程式人生 > >洛谷P1129 [ZJOI2007] 矩陣遊戲

洛谷P1129 [ZJOI2007] 矩陣遊戲

範圍 .... ... ons target problem spl 分享圖片 \n

  題目傳送門

  分析:看到這題呢,首先想到的就是搜索,數據範圍也不大嘛。但是仔細思考發現這題用搜索很難做,看了大佬們的題解後學到了,這一類題目要用二分圖匹配來做。可以知道,如果想要的話,每一個子都可以移動到任意位置(當然會對其他子造成影響),我們還可以發現,每一行或每一列有哪些子其實絕對是固定的,只是它們之間的相對順序會改變。

  瞎扯了這麽多,進入正題吧,首先如果a[i][j]是黑子,那麽我們想要得到的目標當然是把它移動到a[i][i],那麽他當前的位置就可以看作j,目標位置是i,那麽就把j和i之間連一條邊,將所有邊連接以後發現這其實是個二分圖,那麽就二分圖匹配啊,如果能滿足有n個匹配那麽就說明目標狀態可以達到(這個應該不難想吧)。所以建邊以後直接匈牙利算法就OK了。(PS:補充一句,建邊的時候別忘了把數組開大點,一開始腦子有洞忘了,結果RE得非常感人......)

  Code:

  

技術分享圖片
 1 //It is made by HolseLee on 3rd Apr 2018
 2 //Luogu.org P1129
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<iostream>
 8 #include<iomanip>
 9 #include<algorithm>
10 const int N=201;
11 int
T,n; 12 int a[N][N],match[N]; 13 int head[N],size; 14 bool vis[N]; 15 struct Node{ 16 int to,next; 17 }edge[50005]; 18 inline int read() 19 { 20 char ch=getchar();int num=0;bool flag=false; 21 while(ch<0||ch>9){if(ch==-)flag=true;ch=getchar();} 22 while(ch>=0&&ch<=
9){num=num*10+ch-0;ch=getchar();} 23 return flag?-num:num; 24 } 25 inline void ready() 26 { 27 size=0; 28 memset(head,-1,sizeof(head)); 29 memset(match,-1,sizeof(match)); 30 memset(vis,false,sizeof(vis)); 31 } 32 inline void add(int x,int y) 33 { 34 edge[++size].to=y; 35 edge[size].next=head[x]; 36 head[x]=size; 37 } 38 inline bool dfs(int x) 39 { 40 for(int i=head[x];i!=-1;i=edge[i].next){ 41 int y=edge[i].to; 42 if(vis[y])continue; 43 vis[y]=true; 44 if(match[y]==-1||dfs(match[y])){ 45 match[y]=x; 46 return true;}} 47 return false; 48 } 49 inline void work() 50 { 51 n=read(); 52 for(int i=1;i<=n;i++) 53 for(int j=1;j<=n;j++) 54 a[i][j]=read(); 55 for(int i=1;i<=n;i++) 56 for(int j=1;j<=n;j++) 57 if(a[i][j])add(j,i); 58 for(int i=1;i<=n;i++){ 59 memset(vis,false,sizeof(vis)); 60 if(!dfs(i)){printf("No\n");return;}} 61 printf("Yes\n"); 62 } 63 int main() 64 { 65 T=read(); 66 while(T--){ 67 ready(); 68 work();} 69 return 0; 70 }
View Code

洛谷P1129 [ZJOI2007] 矩陣遊戲