zoukankan      html  css  js  c++  java
  • HDU 4687 Boke and Tsukkomi (一般图最大匹配)【带花树】

    <题目链接>

    题目大意:

    给你n个点和m条边,每条边代表两点具有匹配关系,问你有多少对匹配是冗余的。

    解题分析:

    所谓不冗余,自然就是这对匹配关系处于最大匹配中,即该匹配关系有意义。那怎样判断该匹配是否在最大匹配中呢?我们可以枚举每一对匹配,然后对其进行取消其匹配关系,对其余的匹配跑一遍最大匹配,如果是原始最大匹配-1,说明这对匹配关系在最大匹配关系中。需要注意的是,删除匹配关系的时候,不经要将该边的匹配关系删除,还需将所有点与这两点之间的匹配关系删除(即相当于删除这两点)。

      1 #include <iostream>
      2 #include <stdio.h>
      3 #include <string.h>
      4 #include <cmath>
      5 #include <algorithm>
      6 #include <queue>
      7 #include <vector>
      8 using namespace std;
      9 #define MAXN 310
     10 #define CLR(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 {
     19     bool inpath[MAXN]={false};
     20     while(1)
     21     {
     22         u=base[u];
     23         inpath[u]=true;
     24         if(match[u]==-1)break;
     25         u=pre[match[u]];
     26     }
     27     while(1)
     28     {
     29         v=base[v];
     30         if(inpath[v])return v;
     31         v=pre[match[v]];
     32     }
     33 }
     34  
     35 //压缩花
     36 void reset(int u,int anc)
     37 {
     38     while(u!=anc)
     39     {
     40         int v=match[u];
     41         inblossom[base[u]]=1;
     42         inblossom[base[v]]=1;
     43         v=pre[v];
     44         if(base[v]!=anc)pre[v]=match[u];
     45         u=v;
     46     }
     47 }
     48  
     49 void contract(int u,int v,int n)
     50 {
     51     int anc=findancestor(u,v);
     52     CLR(inblossom,0);
     53     reset(u,anc);reset(v,anc);
     54     if(base[u]!=anc)pre[u]=v;
     55     if(base[v]!=anc)pre[v]=u;
     56     for(int i=1;i<=n;i++)
     57         if(inblossom[base[i]])
     58         {
     59             base[i]=anc;
     60             if(!inque[i])
     61             {
     62                 Q.push_back(i);
     63                 inque[i]=1;
     64             }
     65         }
     66 }
     67  
     68 bool dfs(int S,int n)
     69 {
     70     for(int i=0;i<=n;i++)pre[i]=-1,inque[i]=0,base[i]=i;
     71     Q.clear();Q.push_back(S);inque[S]=1;
     72     while(!Q.empty())
     73     {
     74         int u=Q.front();Q.pop_front();
     75         for(int v=1;v<=n;v++)
     76         {
     77             if(g[u][v]&&base[v]!=base[u]&&match[u]!=v)
     78             {
     79                 if(v==S||(match[v]!=-1&&pre[match[v]]!=-1))contract(u,v,n);
     80                 else if(pre[v]==-1)
     81                 {
     82                     pre[v]=u;
     83                     if(match[v]!=-1)Q.push_back(match[v]),inque[match[v]]=1;
     84                     else
     85                     {
     86                         u=v;
     87                         while(u!=-1)
     88                         {
     89                             v=pre[u];
     90                             int w=match[v];
     91                             match[u]=v;
     92                             match[v]=u;
     93                             u=w;
     94                         }
     95                         return true;
     96                     }
     97                 }
     98             }
     99         }
    100     }
    101     return false;
    102 }
    103  
    104 int solve(int n)   
    105 {
    106     CLR(match,-1);
    107     int ans=0;
    108     for(int i=1;i<=n;i++)
    109         if(match[i]==-1&&dfs(i,n))
    110             ans++;
    111     return ans;
    112 }
    113 /*--  以上为带花树求一般图最大匹配的模板   --*/
    114 bool vis[200];
    115 int a[200],b[200];
    116 int main() {
    117     int n , m;
    118     while(scanf("%d%d",&n,&m) != EOF) {
    119         CLR(g,false);CLR(vis,false);
    120        for(int i = 1; i <= m; i++) {
    121            scanf("%d%d",&a[i],&b[i]);
    122            g[a[i]][b[i]] = g[b[i]][a[i]] = true;
    123        }
    124        int ans = solve(n);
    125        vector<int> vec;
    126        for(int i = 1; i <= m; i++) {   //枚举不进行匹配边
    127            int x = a[i]  , y = b[i];
    128            CLR(g,false);     //清空匹配关系,接下来进行重置 
    129            for(int j = 1; j <= m; j++) if(i!=j){
    130                int tmp1 = a[j] , tmp2 = b[j];
    131                if(tmp1==x||tmp1==y||tmp2==x||tmp2==y)continue;   //为什么是将所有包含这两点之间匹配关系的全部(即删除点)清除 ??? 
    132                g[tmp1][tmp2] = g[tmp2][tmp1] = true;
    133            }
    134            int tmp = solve(n);
    135            if(tmp != ans - 1) {   //如果删除这条边后,最大匹配数不是原始值-1,说明这条边不在最大匹配中 
    136                    vec.push_back(i);
    137            }
    138        }      
    139        printf("%d
    ",vec.size());
    140        if(vec.size()>0) {
    141            printf("%d",vec[0]);
    142            for(int i = 1; i < vec.size(); i++) {
    143                printf(" %d",vec[i]);
    144            }
    145        }
    146        puts("");
    147     }
    148     return 0;
    149 }

    2018-11-19

  • 相关阅读:
    Httpd服务入门知识-Httpd服务常见配置案例之虚拟主机
    Httpd服务入门知识-Httpd服务常见配置案例之Apache的工作做状态status页面
    Httpd服务入门知识-Httpd服务常见配置案例之ServerSignature指令选项
    Httpd服务入门知识-Httpd服务常见配置案例之实现用户家目录的http共享
    Httpd服务入门知识-Httpd服务常见配置案例之定义路径别名
    Httpd服务入门知识-Httpd服务常见配置案例之设定默认字符集
    Httpd服务入门知识-Httpd服务常见配置案例之日志设定
    Httpd服务入门知识-Httpd服务常见配置案例之基于客户端来源地址实现访问控制
    瞠目结舌的一幕即将出现,朝韩:明修栈道暗度陈仓
    Flex+blazeds实现与mySQL数据库的连接(已成功实现此文的例子)
  • 原文地址:https://www.cnblogs.com/00isok/p/9986666.html
Copyright © 2011-2022 走看看