zoukankan      html  css  js  c++  java
  • URAL 1099 Work Scheduling (一般图最大匹配) 模板题【带花树】

    <题目链接>

    <转载于 >>>  >

    题目大意:
     给出n个士兵,再给出多组士兵之间两两可以匹配的关系。已知某个士兵最多只能与一个士兵匹配。求最多能够有多少对匹配,并输出这些匹配。

    解题分析:
    本题不一定是二分图,所以求最大匹配不能用匈牙利,因为该一般图可能出现奇环。本题用带花树求解,下面是带花树的模板。

      1 #include <iostream>  
      2 #include <stdio.h>  
      3 #include <string.h>  
      4 #include <cmath>  
      5 #include <algorithm>  
      6 #include <queue>  
      7 using namespace std;  
      8 #define MAXE 250*250*2  
      9 #define MAXN 250  
     10 #define SET(a,b) memset(a,b,sizeof(a))  
     11 deque<int> Q;  
     12 //g[i][j]存放关系图:i,j是否有边,match[i]存放i所匹配的点  
     13 bool g[MAXN][MAXN],inque[MAXN],inblossom[MAXN];  
     14 int match[MAXN],pre[MAXN],base[MAXN];  
     15   
     16 //找公共祖先  
     17 int findancestor(int u,int v){  
     18     bool inpath[MAXN]={false};  
     19     while(1){  
     20         u=base[u];  
     21         inpath[u]=true;  
     22         if(match[u]==-1)break;  
     23         u=pre[match[u]];  
     24     }  
     25     while(1){  
     26         v=base[v];  
     27         if(inpath[v])return v;  
     28         v=pre[match[v]];  
     29     }  
     30 }  
     31   
     32 //压缩花  
     33 void reset(int u,int anc){  
     34     while(u!=anc){  
     35         int v=match[u];  
     36         inblossom[base[u]]=1;  
     37         inblossom[base[v]]=1;  
     38         v=pre[v];  
     39         if(base[v]!=anc)pre[v]=match[u];  
     40         u=v;  
     41     }  
     42 }  
     43   
     44 void contract(int u,int v,int n){  
     45     int anc=findancestor(u,v);  
     46     memset(inblossom,0,sizeof(inblossom));  
     47     reset(u,anc);reset(v,anc);  
     48     if(base[u]!=anc)pre[u]=v;  
     49     if(base[v]!=anc)pre[v]=u;  
     50     for(int i=1;i<=n;i++)  
     51         if(inblossom[base[i]]){  
     52             base[i]=anc;  
     53             if(!inque[i]){  
     54                 Q.push_back(i);  
     55                 inque[i]=1;  
     56             }  
     57         }  
     58 }  
     59   
     60 bool dfs(int S,int n){  
     61     for(int i=0;i<=n;i++)pre[i]=-1,inque[i]=0,base[i]=i;  
     62     Q.clear();Q.push_back(S);inque[S]=1;  
     63     while(!Q.empty()){  
     64         int u=Q.front();Q.pop_front();  
     65         for(int v=1;v<=n;v++){  
     66             if(g[u][v]&&base[v]!=base[u]&&match[u]!=v){  
     67                 if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n);  
     68                 else if(pre[v]==-1){  
     69                     pre[v]=u;  
     70                     if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1;  
     71                     else{  
     72                         u=v;  
     73                         while(u!=-1){  
     74                             v=pre[u];  
     75                             int w=match[v];  
     76                             match[u]=v;  
     77                             match[v]=u;  
     78                             u=w;  
     79                         }  
     80                         return true;  
     81                     }  
     82                 }  
     83             }  
     84         }  
     85     }  
     86     return false;  
     87 }  
     88 int main(){  
     89     int n,m,a,b,ans;  
     90     while(scanf("%d",&n)!=EOF){  
     91         ans=0;         
     92         memset(match,-1,sizeof(match));  
     93         memset(g,0,sizeof(g));  
     94         while(scanf("%d%d",&a,&b)!=EOF&&a!=0){  
     95             g[a][b]=g[b][a]=1;  
     96         }  
     97         for(int i=1;i<=n;i++){  
     98             if(match[i]==-1&&dfs(i,n)){  
     99                 ans++;    //ans记录最多有几对匹配
    100             }  
    101         }  
    102         cout<<ans*2<<endl;   //输出巡逻的人数
    103         for(int i=1;i<=n;i++){  
    104             if(match[i]!=-1){  
    105                 printf("%d %d
    ",i,match[i]);  
    106                 match[i]=match[match[i]]=-1;  
    107             }  
    108         }  
    109     }  
    110     return 0;  
    111 }  

    2018-11-19

  • 相关阅读:
    JavaScript没有块级作用域
    JavaScript数据类型
    接口
    Linux用户与组别的操作
    解决 macOS 下 SSH 空闲一段时间后自动断开
    Excel 系列一 之 账户类长数字打开不截断与完全显示
    怎样花两年时间去面试一个人
    北京大学硕士学位论文模板
    Mysql: 图解 inner join、left join、right join、full outer join、union、union all的区别
    刷 LeetCode 时再学习 Python 中引用
  • 原文地址:https://www.cnblogs.com/00isok/p/9986150.html
Copyright © 2011-2022 走看看