POJ 3020 Antenna Placement 解题报告
题意就不说了,求二部图最大匹配。
问题是怎么建图……
给定的条件中,h<40,w<10,所以笔者直接默认所有情况的地图都是40*10,当然,超出范围的便是空城o。
然后给城市编号。一个城市只能和上下左右4个城市公用天线。换个换说就像国际象棋的棋盘一样,黑色格子与白色格子自然分成了二部图。黑色只能和白色匹配。
编号也很简单了。从第一行开始,第一格是黑色城市1,然后白色城市1,然后黑色城市2,白色城市2……因为所有的图都默认一样大小,所以编号可以重用。
为了方便知道(i,j)到底是黑色还是白色,我们可以用正数编号表示黑色,负数编号表示白色。
然后求最大匹配,直接匈牙利过去就好了。
贴代码,0MS
#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()); } }
整个建图是自己想的,好像略似繁琐……不过还好,比赛的时候估计也能这么想到吧。