zoukankan      html  css  js  c++  java
  • 图论:带花树算法-一般图最大权匹配

    二分图最大权匹配是KM算法,我可以想到可行顶标和相等子图

    一般图的最大权匹配还是带花树算法

    不带权的匹配默认权是1

      1 #include <bits/stdc++.h>
      2 #define N 810
      3 using namespace std;
      4 typedef long long ll;
      5 inline int read()
      6 {
      7     int x=0,f=1; char ch=getchar();
      8     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
      9     while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
     10     return x*f;
     11 }
     12 struct edge{int u,v,w;}mps[N][N];
     13 int n,m,mat[N],pre[N],bl[N],fa[N],tim;ll totw=0;
     14 int sign[N],lab[N],slacku[N],blofm[N][N],tot,mx;
     15 vector <int> leaves[N];
     16 int q[N],hd;
     17 inline int calc_e(const edge &e)
     18 {
     19     return lab[e.u]+lab[e.v]-mps[e.u][e.v].w*2;
     20 }
     21 inline void updata(int u,int x)
     22 {
     23     if(!slacku[x]||calc_e(mps[u][x])<calc_e(mps[slacku[x]][x]))
     24         slacku[x]=u;
     25 }
     26 inline void calc_slack(int x)
     27 {
     28     slacku[x]=0; 
     29     for(int i=1;i<=n;i++)
     30         if(mps[i][x].w>0&&fa[i]!=x&&sign[fa[i]]==0)
     31             updata(i,x);
     32 }
     33 inline void q_push(int x)
     34 {
     35     if(x<=n) q[++hd]=x;
     36     else for(int i=0;i<(int)leaves[x].size();i++)
     37         q_push(leaves[x][i]); 
     38 }
     39 inline int get_lca(int x, int y)
     40 {
     41     if(tim=100000000) 
     42         memset(bl,0,sizeof bl),tim=0;
     43     for(++tim;x||y;swap(x,y)) if(x)
     44     {
     45         if(bl[x]==tim) return x;
     46         bl[x]=tim; x=fa[mat[x]];
     47         if(x) x=fa[pre[x]];
     48     }
     49     return 0;
     50 }
     51 inline void set_fa(int x,int y)
     52 {
     53     fa[x]=y; if(x>n) 
     54     for(int i=0;i<(int)leaves[x].size();i++)
     55         set_fa(leaves[x][i],y);
     56 }
     57 inline void set_mat(int x,int y)
     58 {
     59     mat[x]=mps[x][y].v;
     60     if(x<=n) return ;
     61     int xr=blofm[x][mps[x][y].u];
     62     int pr=find(leaves[x].begin(),leaves[x].end(),xr)-leaves[x].begin();
     63     if(pr%2==1)
     64         reverse(leaves[x].begin()+1, leaves[x].end()),
     65         pr=(int)leaves[x].size()-pr;
     66     for(int i=0;i<pr;i++)
     67         set_mat(leaves[x][i],leaves[x][i^1]);
     68     set_mat(xr,y);
     69     rotate(leaves[x].begin(),leaves[x].begin()+pr,leaves[x].end());
     70 }
     71 inline void blossom_blooms(int x)
     72 {
     73     for(int i=0;i<(int)leaves[x].size();i++)
     74     {
     75         if(leaves[x][i]>n&&!lab[leaves[x][i]])
     76             blossom_blooms(leaves[x][i]);
     77         else set_fa(leaves[x][i],leaves[x][i]);
     78     }
     79     fa[x]=0;
     80 }
     81 inline void blossom_make(int u,int lca,int v)
     82 {
     83     int x=n+1; while(x<=tot&&fa[x]) x++;
     84     if(x>tot) tot++; 
     85     lab[x]=sign[x]=0;
     86     mat[x]=mat[lca]; leaves[x].clear();
     87     leaves[x].push_back(lca);
     88     for(int i=u;i!=lca;i=fa[pre[fa[mat[i]]]])
     89         leaves[x].push_back(i),leaves[x].push_back(fa[mat[i]]),q_push(fa[mat[i]]);
     90     reverse(leaves[x].begin()+1, leaves[x].end());
     91     for(int i=v;i!=lca;i=fa[pre[fa[mat[i]]]])
     92         leaves[x].push_back(i),leaves[x].push_back(fa[mat[i]]),q_push(fa[mat[i]]);
     93     set_fa(x,x);
     94     for(int i=1;i<=tot;i++)
     95         mps[x][i].w=mps[i][x].w=0, blofm[x][i]=0;
     96     for(int i=0;i<(int)leaves[x].size();i++)
     97     {
     98         int xs=leaves[x][i];
     99         for(int j=1;j<=tot;j++)
    100             if(!mps[x][j].w||calc_e(mps[xs][j])<calc_e(mps[x][j]))
    101                 mps[x][j]=mps[xs][j],mps[j][x]=mps[j][xs];
    102         for(int j=1;j<=tot;j++)
    103             if(blofm[xs][j]) blofm[x][j]=xs;
    104     }
    105     calc_slack(x);
    106 }
    107 inline void link(int x,int y)
    108 {
    109     while(1)
    110     {
    111         int xx=fa[mat[x]];
    112         set_mat(x,y);
    113         if(!xx) return ;
    114         set_mat(xx,fa[pre[xx]]);
    115         x=fa[pre[xx]]; y=xx;
    116     }
    117 }
    118 inline int deal_edge(const edge &e)
    119 {
    120     int u=fa[e.u],v=fa[e.v];
    121     if(sign[v]==-1) //unsigned
    122     {
    123         pre[v]=e.u; // cause we bfs all vertices tegother,we dont' need to discuss two situation 
    124         sign[v]=1; sign[fa[mat[v]]]=0;
    125         slacku[v]=slacku[fa[mat[v]]]=0;
    126         q_push(fa[mat[v]]);
    127     }
    128     else if(!sign[v]) //S signed vertex
    129     {
    130         int lca=get_lca(u,v);
    131         if(!lca)
    132         {
    133             link(u,v); link(v,u); //connected! new argument.
    134             for(int i=n+1;i<=tot;i++)
    135                 if(fa[i]==i&&lab[i]==0)
    136                     blossom_blooms(i); // flower may not be a flower any more so we blossom blooms!
    137             return 1;
    138         }
    139         else blossom_make(u,lca,v); // form a new flower!
    140     }
    141     return 0;
    142 }
    143 inline void blossom_bloom_1(int x)
    144 {
    145 
    146     for(int i=0;i<(int)leaves[x].size();i++)
    147         set_fa(leaves[x][i],leaves[x][i]);
    148     int xr=blofm[x][mps[x][pre[x]].u];
    149     int pr=find(leaves[x].begin(), leaves[x].end(),xr)-leaves[x].begin();
    150     if(pr%2==1) 
    151         reverse(leaves[x].begin()+1, leaves[x].end()),
    152         pr=(int)leaves[x].size()-pr;
    153     for(int i=0;i<pr;i+=2)
    154     {
    155         int u=leaves[x][i],v=leaves[x][i+1];
    156         pre[u]=mps[v][u].u;
    157         sign[u]=1; sign[v]=0;
    158         slacku[u]=0; calc_slack(v); q_push(v);
    159     }    
    160     sign[xr]=1; pre[xr]=pre[x];
    161     for(int i=pr+1;i<(int)leaves[x].size();i++)
    162     {
    163         int u=leaves[x][i];
    164         sign[u]=-1; calc_slack(u);
    165     }
    166     fa[x]=0;
    167 }
    168 inline int match()
    169 {
    170     for(int i=1;i<=tot;i++) slacku[i]=0,sign[i]=-1;
    171     hd=0; for(int i=1;i<=tot;i++)
    172         if(fa[i]==i&&!mat[i])
    173             slacku[i]=pre[i]=sign[i]=0,q_push(i);
    174     if(!hd) return 0; 
    175     while(1)
    176     {
    177         for(int i=1;i<=hd;i++)
    178         {
    179             int lx=q[i]; for(int j=1;j<=n;j++)
    180                 if(mps[lx][j].w>0&&fa[lx]!=fa[j])
    181                 {
    182                     if(!calc_e(mps[lx][j]))
    183                     {
    184                         if(deal_edge(mps[lx][j])) 
    185                             return 1;
    186                     }
    187                     else if(sign[fa[j]]!=1) updata(lx,fa[j]);
    188                 }
    189         }
    190         int d=0x3fffffff;
    191         for(int i=1;i<=n;i++) if(!sign[fa[i]])
    192             d=min(d,lab[i]);
    193         for(int i=n+1;i<=tot;i++)
    194             if(fa[i]==i&&sign[i]==1)
    195                 d=min(lab[i]/2,d);
    196         for(int i=1;i<=tot;i++) if(fa[i]==i&&slacku[i])
    197         {
    198             if(sign[i]==-1) d=min(calc_e(mps[slacku[i]][i]),d);
    199             else if(sign[i]==0) d=min(calc_e(mps[slacku[i]][i])/2,d);
    200         }
    201         for(int i=1;i<=n;i++)
    202             if(sign[fa[i]]==0) lab[i]-=d;
    203             else if (sign[fa[i]]==1) lab[i]+=d;
    204         for(int i=n+1;i<=tot;i++)
    205             if(fa[i]==i)
    206             {
    207                 if(sign[i]==0) lab[i]+=d*2; 
    208                 else if(sign[i]==1) lab[i]-=d*2;
    209             }
    210         hd=0;
    211         for(int i=1;i<=n;i++) if(!lab[i]) return 0; //all vetices matched,single vetices's label = 0
    212         for(int i=1;i<=tot;i++)
    213             if(fa[i]==i&&slacku[i]&&fa[slacku[i]]!=i&&calc_e(mps[slacku[i]][i])==0)
    214                 /*new edge*/ if(deal_edge(mps[slacku[i]][i])) return 1;
    215         for(int i=n+1;i<=tot;i++)
    216             if(fa[i]==i&&sign[i]==1&&!lab[i])
    217                 blossom_bloom_1(i);
    218     }
    219     return 0;
    220 }
    221 inline void solve()
    222 {
    223     for(int i=1;i<=n;i++) mat[i]=0;
    224     tot=n; hd=totw=0;  
    225     for(int i=0;i<=n;i++) fa[i]=i,leaves[i].clear();
    226     for(int i=1;i<=n;i++) for(int j=1;j<=n;j++)
    227         blofm[i][j]=(i==j? i:0);
    228     for(int i =1;i<=n;i++) lab[i]=mx; //init label
    229     while(match());
    230     for(int i=1;i<=n;i++) if(mat[i]&&mat[i]<i)
    231         totw+=mps[i][mat[i]].w;
    232 }
    233 int main()
    234 {
    235     n=read(); m=read();
    236     for(int i=1;i<=n;i++)
    237         for(int j=1;j<=n;j++)
    238             mps[i][j]=(edge){i,j,0};
    239     for(int i=1;i<=m;i++)
    240     {
    241         int u=read(), v=read(), w=read();
    242         mps[u][v].w=mps[v][u].w=w; mx=max(mx,w);
    243     }
    244     solve(); printf("%lld
    ",totw);
    245     for(int i=1;i<=n;i++)
    246         printf("%d ",mat[i]); 
    247     puts("");
    248     return 0;
    249 }

    代码量简直了

  • 相关阅读:
    关系型数据库——主键&外键的
    JSON运用——PHP中使用json数据格式定义字面量对象的方法
    JSON.parse与eval的区别
    css中那些属性可以被继承
    js笔记 -- toString() 和String()
    MYSQL IFNULL函数的使用
    mysql临时表产生的执行效率问题改进(转)
    mysql中concat 和 group_concat()的用法
    转载mysql数据库配置优化
    浅谈MySql的存储引擎(转)
  • 原文地址:https://www.cnblogs.com/aininot260/p/9623764.html
Copyright © 2011-2022 走看看