題意就不說了,求二部圖最大匹配。spa
問題是怎麼建圖……code
給定的條件中,h<40,w<10,因此筆者直接默認全部狀況的地圖都是40*10,固然,超出範圍的即是空城o。blog
而後給城市編號。一個城市只能和上下左右4個城市公用天線。換個換說就像國際象棋的棋盤同樣,黑色格子與白色格子天然分紅了二部圖。黑色只能和白色匹配。string
編號也很簡單了。從第一行開始,第一格是黑色城市1,而後白色城市1,而後黑色城市2,白色城市2……由於全部的圖都默認同樣大小,因此編號能夠重用。io
爲了方便知道(i,j)究竟是黑色仍是白色,咱們能夠用正數編號表示黑色,負數編號表示白色。class
而後求最大匹配,直接匈牙利過去就行了。地圖
貼代碼,0MSdi
#include <cstdio> #include <cstring> const int maxn=201; bool mp[maxn][maxn]; bool vis[maxn]; int link[maxn]; int No[41][10]; int n; bool DFS(int x) { for(int y=1;y<=n;y++) { if(mp[x][y] && !vis[y]) { vis[y]=true; if(link[y]==0 || DFS(link[y])) { link[y]=x; return true; } } } return false; } int maxMartch() { int count=0; for(int x=1;x<=n;x++) { memset(vis,0,sizeof(vis)); if(DFS(x)) count++; } return count; } int main() { int T; scanf("%d",&T); int index=2; for(int i=0;i<40;i++) for(int j=0;j<10;j++,index++) No[i][j]=(index/2)*((index+i)%2?-1:1); n=200; while(T--) { int num=0; int w,h; scanf("%d%d",&h,&w); if(w%2) w++; char str[2][20]; memset(mp,0,sizeof(mp)); memset(link,0,sizeof(link)); memset(str,0,sizeof(str)); for(int i=0;i<h;i++) { scanf("%s",str[i&1]); if(str[i&1][0]=='*') { num++; if(str[1-i&1][0]=='*') { if(No[i][0]>0) mp[No[i][0]][-No[i-1][0]]=true; else mp[No[i-1][0]][-No[i][0]]=true; } } for(int j=1; j<w; j++) { if(str[i&1][j]=='*') { num++; if(str[i&1][j-1]=='*') { if(No[i][j]>0) mp[No[i][j]][-No[i][j-1]]=true; else mp[No[i][j-1]][-No[i][j]]=true; } if(str[1-i&1][j]=='*') { if(No[i][j]>0) mp[No[i][j]][-No[i-1][j]]=true; else mp[No[i-1][j]][-No[i][j]]=true; } } } } printf("%d\n",num-maxMartch()); } }
整個建圖是本身想的,好像略似繁瑣……不過還好,比賽的時候估計也能這麼想到吧。vi