题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3468
大牛思路:
用BFS找出每一个集合点到其它可达点的距离以及这个集合点到下一集合点的距离
枚举是否能从一个集合点K经过一个宝物点X到达下一个集合点(K+1).如果能的话,则path[K][X]=true;
如果发现有一个集合点不可达的话,则输出-1;
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 #define MAXN 110 8 char map[MAXN][MAXN]; 9 int dd[MAXN];//保存相邻集合点之间的距离 10 int dist[MAXN][MAXN*MAXN];//保存集合点到图中任意一点之间的距离 11 bool mark[MAXN*MAXN]; 12 bool path[MAXN][MAXN*MAXN];//标记二部图x与y的连通性 13 int match[MAXN*MAXN];//匹配 14 int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}}; 15 int n,m,p,q; 16 17 int GetId(char ch){ 18 if(ch>='A'&&ch<='Z')return ch-'A'; 19 return ch-'a'+26; 20 } 21 22 void bfs(int x,int y,int id){ 23 queue<int>Q; 24 Q.push(x),Q.push(y); 25 dist[id][x*m+y]=0; 26 while(!Q.empty()){ 27 x=Q.front();Q.pop(); 28 y=Q.front();Q.pop(); 29 int d=dist[id][x*m+y]; 30 for(int i=0;i<4;i++){ 31 int xx=x+dir[i][0]; 32 int yy=y+dir[i][1]; 33 if(xx>=0&&xx<n&&yy>=0&&yy<m&&map[xx][yy]!='#'&&dist[id][xx*m+yy]==-1){ 34 dist[id][xx*m+yy]=d+1; 35 Q.push(xx),Q.push(yy); 36 if(isalpha(map[xx][yy])&&(GetId(map[xx][yy])==id+1)){ 37 dd[id]=d+1; 38 } 39 } 40 } 41 } 42 } 43 44 45 46 bool dfs(int k,int m){ 47 for(int i=0;i<m;i++){ 48 if(path[k][i]&&!mark[i]){ 49 mark[i]=true; 50 if(match[i]==-1||dfs(match[i],m)){ 51 match[i]=k; 52 return true; 53 } 54 } 55 } 56 return false; 57 } 58 59 60 int Hungary(int n,int m){ 61 int ans=0; 62 memset(match,-1,sizeof(match)); 63 for(int i=0;i<n;i++){ 64 memset(mark,false,sizeof(mark)); 65 if(dfs(i,m))ans++; 66 } 67 return ans; 68 } 69 70 71 int main(){ 72 while(~scanf("%d%d",&n,&m)){ 73 memset(dist,-1,sizeof(dist)); 74 memset(dd,-1,sizeof(dd)); 75 memset(path,false,sizeof(path)); 76 p=q=0; 77 for(int i=0;i<n;i++){ 78 scanf("%s",map[i]); 79 } 80 for(int i=0;i<n;i++){ 81 for(int j=0;j<m;j++){ 82 if(isalpha(map[i][j])){ 83 p=max(p,GetId(map[i][j])); 84 bfs(i,j,GetId(map[i][j])); 85 } 86 } 87 } 88 bool flag=true; 89 for(int i=0;i<p;i++){ 90 if(dd[i]==-1){ flag=false;break; } 91 } 92 if(!flag){ puts("-1");continue; } 93 for(int i=0;i<n;i++){ 94 for(int j=0;j<m;j++){ 95 if(map[i][j]=='*'){ 96 for(int k=0;k<p;k++){ 97 //判断金子是否在最短路上 98 if(dist[k][i*m+j]+dist[k+1][i*m+j]==dd[k]){ 99 path[k][q]=true; 100 } 101 } 102 q++; 103 } 104 } 105 } 106 printf("%d\n",Hungary(p+1,q)); 107 } 108 return 0; 109 }