• hdu 3468(二分匹配)


    题目链接: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 }
    View Code
  • 相关阅读:
    LCS 最长公共子序列
    零和数组
    Learn2Rank
    ac自动机
    208. Implement Trie (Prefix Tree)
    php截取中文字符串 GB2312 utf-8
    纵向文字滚动代码,带上下图片控制的。鼠标放到上下图片上时滚动
    js图片切换 带左右控制的
    实时显示输入的内容
    Lightbox JS v2.0图片切换效果
  • 原文地址:https://www.cnblogs.com/wally/p/3089138.html
Copyright © 2020-2023  润新知