题意就不说了,求二部图最大匹配。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