zoukankan      html  css  js  c++  java
  • 二分图最大匹配

    题目链接:here

    题解:

    BFS+二分图最大匹配。
    这题的入手点就是休息点的个数比较小,最多52个。
    首先对每个休息点跑一遍BFS,记录休息点到每个点的最短距离。
    判断某个金矿是否在两个休息点之间可以被采集到:
    例如判断某金矿与BC路径,如果这个金矿与B的最短距离加上这个金矿与C的最短距离等于B与C的最短距离,则代表这个金矿在BC路径上可以被采集到。
    然后建二分图,一边是金矿,另一边是路径,如果某个金矿能在某条路径上能被采集到,则建边。
    最后跑一次二分图最大匹配,就是答案。

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=110;
      4 const int inf=0x3f3f3f3f;
      5 char s[maxn][maxn];
      6 
      7 struct Edge{
      8     int v,nex;
      9 }e[maxn*maxn];
     10 int head[maxn];
     11 int cnt=0;
     12 
     13 void init(){
     14     memset(head,-1,sizeof(head));
     15     cnt=0;
     16 }
     17 void add(int u,int v){
     18     e[cnt].v=v;
     19     e[cnt].nex=head[u];
     20     head[u]=cnt++;
     21 }
     22 int n,m;
     23 int d[66][maxn][maxn];
     24 struct Node{
     25     int x,y;
     26 }a,b;
     27 int vis[maxn][maxn];
     28 int slo[66][66];
     29 
     30 int dir[4][2]={0,1,0,-1,1,0,-1,0};
     31 void bfs(int x,int y,int id){
     32     memset(vis,0,sizeof(vis));
     33     queue<Node> q;
     34     a.x=x;a.y=y;
     35     d[id][x][y]=0;
     36     q.push(a);
     37     vis[x][y]=1;
     38     while(!q.empty()){
     39         a=q.front();
     40         q.pop();
     41         if(id==25&&s[a.x][a.y]=='a') slo[id][id+1]=d[id][a.x][a.y];
     42         else if(id<25&&s[a.x][a.y]-'A'==id+1) slo[id][id+1]=d[id][a.x][a.y];
     43         else if(id>25&&s[a.x][a.y]-'a'+26==id+1) slo[id][id+1]=d[id][a.x][a.y];
     44         for(int i=0;i<4;i++){
     45             b.x=a.x+dir[i][0];
     46             b.y=a.y+dir[i][1];
     47             if(b.x>=0&&b.x<n&&b.y>=0&&b.y<m&&!vis[b.x][b.y]&&s[b.x][b.y]!='#') {
     48                 d[id][b.x][b.y]=d[id][a.x][a.y]+1;
     49                 vis[b.x][b.y]=1;
     50                 q.push(b);
     51             }
     52         }
     53     }
     54 }
     55 int vb[maxn*maxn];
     56 int match[maxn*maxn];
     57 
     58 int Hungary(int u){
     59     for(int i=head[u];~i;i=e[i].nex){
     60         int v=e[i].v;
     61         if(!vb[v]){
     62             vb[v]=1;
     63             if(match[v]==-1||Hungary(match[v])){
     64                 match[v]=u;
     65                 return 1;
     66             }
     67         }
     68     }
     69     return 0;
     70 }
     71 
     72 int main(){
     73     while(scanf("%d%d",&n,&m)!=EOF){
     74         memset(d,inf,sizeof(d));
     75         memset(slo,inf,sizeof(slo));
     76         init();
     77         int st=0;
     78         for(int i=0;i<n;i++) scanf("%s",s[i]);
     79         for(int i=0;i<n;i++){
     80             for(int j=0;j<m;j++){
     81                 if(isupper(s[i][j])) bfs(i,j,s[i][j]-'A'),st++;
     82                 if(islower(s[i][j])) bfs(i,j,s[i][j]-'a'+26),st++;
     83             }
     84         }
     85         int ok = 0;
     86         for(int i=0;i<st-1;i++) if(slo[i][i+1]==inf) {
     87             puts("-1");
     88             ok = 1;
     89             break;
     90         }
     91         if(ok) continue;
     92       //  for(int i=0;i<st;i++) printf("---%d
    ",slo[i][i+1]);
     93         /*
     94         int id;
     95         while(scanf("%d",&id)){
     96         for(int i=0;i<n;i++)
     97             for(int j=0;j<m;j++) printf("%d%c",d[id][i][j],j==m-1?'
    ':' ');
     98         }
     99         */
    100         int gold=0;
    101         for(int i=0;i<n;i++){
    102             for(int j=0;j<m;j++){
    103                 if(s[i][j]=='*'){
    104                     for(int k=0;k<st-1;k++){
    105                         if(d[k][i][j]+d[k+1][i][j]==slo[k][k+1]){
    106                             add(k,gold);
    107                         }
    108                     }
    109                     gold++;
    110                 }
    111             }
    112         }
    113         int ans=0;
    114         memset(match,-1,sizeof(match));
    115         for(int i=0;i<st-1;i++){
    116             memset(vb,0,sizeof(vb));
    117             if(Hungary(i)) ans++;
    118         }
    119         printf("%d
    ",ans);
    120     }
    121     return 0;
    122 }
    View Code
  • 相关阅读:
    Linux启动新进程的几种方法及比较[转]
    部署WEB应用的三种方式[转]
    HTML form label
    其他对象的表单
    Input对象2(貌似是独立标签)
    通过表单展示不一样的页面(input对象)
    神奇的表单
    有效地管理页面布局
    css新奇技术及其未来发展
    进一步讨论页面布局的方法
  • 原文地址:https://www.cnblogs.com/yijiull/p/7648460.html
Copyright © 2011-2022 走看看