• BZOJ 4405 [wc2016]挑战NPC 带花树 一般图最大匹配


    https://www.lydsy.com/JudgeOnline/problem.php?id=4405

    这道题大概就是考场上想不出来,想出来也调不出来的题。

    把每个桶拆成三个互相有边的点,每个球向它连接的桶的三个点分别连边。

    0球1桶,匹配数为1;1球1桶,匹配数为2;2球一桶,匹配数为2;3球一桶,匹配数为3;

    发现每种半桶的情况下匹配数都比该桶中放的球数大1,那么ans=最大匹配数-球数。

    带花树找lca的时候,记得是用每个点的总父亲找。带花树的细节真是恶心人。

     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=730010;
    10 const int maxm=610;
    11 int n,m,siz;
    12 struct nod{
    13     int y,next;
    14 }e[maxn];int head[maxm]={},tot=0;
    15 int q[maxn]={},tl,tr;
    16 int bel[maxm]={},tly,d[maxm]={},pre[maxm]={},tp[maxm]={},fa[maxm]={};
    17 inline 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         }swap(x,y);        
    29     }
    30 }
    31 inline void mlink(int x,int y,int pa){
    32     while(getfa(x)!=pa){
    33         pre[x]=y;y=d[x];
    34         if(tp[y]==2){tp[y]=1;q[++tr]=y;}
    35         if(getfa(x)==x)fa[x]=pa;
    36         if(getfa(y)==y)fa[y]=pa;
    37         x=pre[y];
    38     }
    39 }
    40 int doit(int s){
    41     for(int i=1;i<=siz;++i)fa[i]=i;
    42     memset(tp,0,sizeof(tp));memset(pre,0,sizeof(pre));
    43     tl=tr=1;q[1]=s;tp[s]=1;
    44     while(tl<=tr){
    45         int x=q[tl];++tl;
    46         for(int i=head[x];i;i=e[i].next){
    47             int y=e[i].y;
    48             if(getfa(y)==getfa(x)||tp[y]==2)continue;//cout<<i<<endl;
    49             if(!tp[y]){
    50                 tp[y]=2;pre[y]=x;//cout<<y<<endl;
    51                 if(!d[y]){
    52                     for(int now=y,j,las;now;now=las){
    53                         j=pre[now];las=d[pre[now]];
    54                         d[j]=now;d[now]=j;
    55                     }//cout<<i<<1<<endl;
    56                     return 1;
    57                 }
    58                 tp[d[y]]=1;q[++tr]=d[y];
    59             }
    60             else{
    61                 int pa=lca(x,y);
    62                 mlink(x,y,pa);mlink(y,x,pa);
    63             }
    64         }
    65     }
    66     return 0;
    67 }
    68 int main(){
    69     int T;scanf("%d",&T);
    70     while(T-->0){
    71         memset(bel,0,sizeof(bel));memset(d,0,sizeof(d));
    72         memset(head,0,sizeof(head));
    73         tot=tly=0;
    74         int p;
    75         scanf("%d%d%d",&n,&m,&p);siz=n+m*3;
    76         int x,y;
    77         for(int i=1;i<=m;++i){
    78             init(i,i+m);init(i+m,i);
    79             init(i,i+m*2);init(i+m*2,i);
    80             init(i+m,i+m*2);init(i+m*2,i+m);
    81         }
    82         for(int i=1;i<=p;++i){
    83             scanf("%d%d",&x,&y);
    84             init(m*3+x,y);init(y,m*3+x);
    85             init(m*3+x,y+m);init(y+m,m*3+x);
    86             init(m*3+x,y+m*2);init(y+m*2,m*3+x);
    87         }
    88         int ans=0;
    89         for(int i=1;i<=siz;++i)if(!d[i])ans+=doit(i);
    90         printf("%d
    ",ans-n);
    91     }
    92     return 0;
    93 }
    View Code

  • 相关阅读:
    ndk与jni学习
    2021杭电多校第十场题解
    2021杭电多校第九场题解
    2021杭电多校第八场题解
    2021杭电多校第七场题解
    2021杭电多校第六场题解
    2021杭电多校第四场题解
    2021杭电多校第五场题解
    2021杭电多校第三场题解
    2021杭电多校第二场题解
  • 原文地址:https://www.cnblogs.com/137shoebills/p/9181309.html
Copyright © 2020-2023  润新知