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 }