• UOJ #79 一般图最大匹配 带花树


    http://uoj.ac/problem/79

    一般图和二分图的区别就是有奇环,带花树是在匈牙利算法的基础上对奇环进行缩点操作,复杂度似乎是O(mn)和匈牙利一样。

    具体操作是一个一个点做类似匈牙利的找增广路操作,每次将一个点作为根(染成白色),然后向下bfs黑白染色,两个白点相邻时将这两个白点缩到割顶成一个点(用并查集维护一下)(匈牙利算法也是只用白点找增广,黑点相当于重复计算了没有意义),然后把奇环里所有黑点视为白点放到队列里bfs。

    设置一个pre数组记录返回的路径(因为bfs的方向和匈牙利是相反的所以最后找到的时候再顺着返回的路径重新匹配),因为重新匹配的时候找的是可匹配的黑点,所以在dfs的时候只用给每个黑点设置pre,产生奇环的时候再对白点设置pre,因为此时奇环里的点匹配之后才能决定颜色(黑白都可以)。

    这个算法,有一丶丶恶心。

    原理详解:https://blog.csdn.net/u014261987/article/details/41249385

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 using namespace std;
     8 #define LL long long
     9 const int maxn=500010;
    10 const int mmm=510;
    11 int n,m;
    12 struct nod{
    13     int y,next;
    14 }e[maxn];
    15 int head[mmm]={},q[maxn]={},tl=0,tr=0,tot=0;
    16 int fa[mmm]={},tp[mmm]={},pre[mmm]={},d[mmm]={},bel[mmm]={},tly=0;
    17 void init(int x,int y){e[++tot].y=y;e[tot].next=head[x];head[x]=tot;}
    18 inline int getfa(int x){
    19     return fa[x]==x?x:fa[x]=getfa(fa[x]);
    20 }
    21 inline int lca(int x,int y){
    22     ++tly;
    23     for(;;){
    24         if(x){
    25             x=getfa(x);
    26             if(bel[x]==tly)return x;
    27             else {bel[x]=tly;x=pre[d[x]];}
    28         }
    29         swap(x,y);
    30     }
    31 }
    32 inline void mlink(int x,int y,int pa){
    33     while(getfa(x)!=pa){
    34         pre[x]=y;y=d[x];
    35         if(tp[y]==2){tp[y]=1;q[++tr]=y;}
    36         if(getfa(x)==x)fa[x]=pa;
    37         if(getfa(y)==y)fa[y]=pa;
    38         x=pre[y];
    39     }
    40 }
    41 int doit(int s){
    42     for(int i=1;i<=n;++i)fa[i]=i;
    43     memset(tp,0,sizeof(tp));memset(pre,0,sizeof(pre));
    44     tl=tr=1;q[1]=s;tp[s]=1;
    45     while(tl<=tr){
    46         int x=q[tl];++tl;
    47         for(int i=head[x];i;i=e[i].next){
    48             int y=e[i].y;
    49             if(getfa(x)==getfa(y)||tp[y]==2)continue;
    50             if(!tp[y]){
    51                 tp[y]=2;pre[y]=x;
    52                 if(!d[y]){
    53                     for(int now=y,las,j;now;now=las){
    54                         j=pre[now]; las=d[pre[now]];
    55                         d[now]=j;d[j]=now;
    56                     }
    57                     return 1;
    58                 }
    59                 tp[d[y]]=1;q[++tr]=d[y];
    60             }
    61             else{
    62                 int pa=lca(x,y);
    63                 mlink(x,y,pa);mlink(y,x,pa);
    64             }
    65         }
    66     }return 0;
    67 }
    68 int main(){
    69     scanf("%d%d",&n,&m);
    70     int x,y;
    71     for(int i=0;i<m;++i){scanf("%d%d",&x,&y);init(x,y);init(y,x);}
    72     int ans=0;
    73     for(int i=1;i<n;++i){if(!d[i])ans+=doit(i);}
    74     printf("%d
    ",ans);
    75     for(int i=1;i<=n;++i)if(d[i])d[d[i]]=i;
    76     for(int i=1;i<=n;++i){
    77         printf("%d ",d[i]);
    78     }printf("
    ");
    79     return 0;
    80 }
    View Code

  • 相关阅读:
    Android渐变GradientDrawable叠加组合环ring
    72.spring boot讨论群【从零开始学Spring Boot】
    71.mybatis 如何获取插入的id【从零开始学Spring Boot】
    Android GradientDrawable的XML实现
    服务器端架构及实战 — C#分享
    70.打印所有Spring boot载入的bean【从零开始学Spring Boot】
    69. JPA实体Bean的生命周期【从零开始学Spring Boot】
    Android版网易云音乐唱片机唱片磁盘旋转及唱片机机械臂动画关键代码实现思路
    服务器架构及实战(架构篇)- PHP建站
    创建MyOffice项目
  • 原文地址:https://www.cnblogs.com/137shoebills/p/9179932.html
Copyright © 2020-2023  润新知