【BZOJ4405】挑战NPC 带花树模板 一般图最大匹配

来源:互联网 发布:世界上第一个程序员是 编辑:程序博客网 时间:2024/06/06 09:02

这段时间被主教练找的各种poj英文题虐的头昏脑涨也没时间来更新博客QAQ

好不容易找了时间来学带花树QAQ

#include<cstdlib>#include<cstdio>#include<iostream>#include<cstring>#include<cmath>#include<algorithm>#include<queue>#include<vector>using namespace std;#define MAXN 2005#define MAXM 200005int N,M,Q,head[MAXN],edge_ct,f[MAXN],mark[MAXN],next[MAXN],match[MAXN];struct edge{int to,next;}e[MAXM];void add(int x,int y){e[++edge_ct]=(edge){y,head[x]}; head[x]=edge_ct; e[++edge_ct]=(edge){x,head[y]};head[y]=edge_ct;}int Find(int x){return f[x]==x ? x : f[x]=Find(f[x]);};int q[MAXN],front,rear;void _read(int &x){x=0; char ch=getchar(); bool flag=false;while(ch<'0' || ch>'9'){if(ch=='-')flag=true;ch=getchar(); }while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} if(flag)x=-x; return ;}int tmp[MAXN],_T;int LCA(int u,int v) //把奇环给找出来 {_T++;while(1){if(u){u=Find(u);if(tmp[u]==_T)return u;tmp[u]=_T;if(match[u])u=next[match[u]];else u=0;}swap(u,v);}}void Link(int a,int p){int b,c;while(a!=p){b=match[a]; c=next[b];if(Find(c)!=p)next[c]=b;if(mark[b]==2)mark[q[rear++]=b]=1;if(mark[c]==2)mark[q[rear++]=c]=1;f[Find(b)]=Find(a);f[Find(b)]=Find(c);a=c;}return ;}void _Find(int now){for(int i=1;i<=N+3*M;i++)mark[i]=next[i]=0,f[i]=i;front=1;rear=1;q[rear++]=now; mark[now]=1; int u,v,p,t;while(front<rear){u=q[front++];for(int id=head[u];id;id=e[id].next){v=e[id].to;if(v==match[u] || mark[v]==2 || Find(u)==Find(v))continue;if(mark[v]==1){p=LCA(u,v);if(Find(u)!=p)next[u]=v;if(Find(v)!=p)next[v]=u;Link(u,p); Link(v,p);}else if(!match[v]){next[v]=u;while(v){u=next[v];t=match[u];match[v]=u; match[u]=v;v=t;}return ;}else{next[v]=u; mark[v]=2; mark[match[v]]=1; q[rear++]=match[v];}}}}void Init(){_read(N); _read(M); _read(Q);_T=0; edge_ct=0; for(int i=1;i<=N+3*M;i++)match[i]=head[i]=tmp[i]=0;int x,y;for(int i=1;i<=Q;i++){_read(x); _read(y); add(x,N+3*y-2);add(x,N+3*y-1);add(x,N+3*y-0);}for(int i=1;i<=M;i++)add(N+3*i-2,N+3*i-1),add(N+3*i-1,N+3*i-0),add(N+3*i-2,N+3*i-0);return ;}void work(){int ans=0;for(int i=1;i<=N+3*M;i++)if(!match[i])_Find(i);for(int i=1;i<=N+3*M;i++)if(match[i])ans++;ans=ans/2; ans=ans-N; printf("%d\n",ans); //for(int i=1;i<=N;i++)printf("%d ",(match[i]-N-1)/3+1);//putchar('\n');return ;}int main(){//freopen("in.txt","r",stdin);int T; _read(T);while(T--){Init();work();}return 0;}


0 0
原创粉丝点击