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\n",ans-n);
91     }
92     return 0;
93 }
View Code

 

posted @ 2018-06-14 08:31  鲸头鹳  阅读(129)  评论(0编辑  收藏  举报