您的位置:首页 > 其它

uoj171 bzoj4405 挑战NPC 一般图最大匹配

2016-03-25 20:46 351 查看
不得不说建图太巧妙了,我在知道是一般图最大匹配的情况下都不会建图。。。

首先每个筐放三个,这个“三”是很关键的。

把一个筐拆成三个点,然后每一个球向可以放的三个筐都连边;同时三个筐之间互相连边。那么如果一个筐只有<=1个点连向了它,那么一定会多一条匹配边;此外由于题中保证存在合法的放球的方案,因此每个点至少能连出一条边,因此基本的边数为N,那么最大匹配边数-N就是答案了。

注意bzoj和uoj上面的输出是不一样的。

AC代码如下(uoj):

#include<iostream>
#include<cstdio>
#include<cstring>
#define N 1005
#define M 250005
using namespace std;

int n,m,cnt,tot,head,tail,dfsclk,h
,fst
,pnt[M],nxt[M],fa
,path
,kind
,match
,pre
;
void add(int x,int y){
pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;
}
int getfa(int x){ return (x==fa[x])?x:fa[x]=getfa(fa[x]); }
int lca(int x,int y){
for (dfsclk++; ; swap(x,y)) if (x){
x=getfa(x);
if (path[x]==dfsclk) return x;
path[x]=dfsclk; x=pre[match[x]];
}
}
void shrink(int x,int y,int k){
while (getfa(x)!=k){
pre[x]=y; int z=match[x];
if (kind[z]==1){ kind[z]=0; h[++tail]=z; }
if (getfa(x)==x) fa[x]=k;
if (getfa(z)==z) fa[z]=k;
y=z; x=pre[y];
}
}
bool bfs(int sta){
int i,x,y,z,p; for (i=1; i<=cnt; i++){ fa[i]=i; kind[i]=-1; }
h[1]=sta; kind[sta]=0; head=0; tail=1;
while (head<tail){
x=h[++head];
for (p=fst[x]; p; p=nxt[p]){
y=pnt[p];
if (kind[y]==-1){
pre[y]=x; kind[y]=1;
if (!match[y]){
int now=y,last;
for (; now; now=last){
last=match[pre[now]];
match[pre[now]]=now; match[now]=pre[now];
}
return 1;
}
kind[match[y]]=0; h[++tail]=match[y];
}
else if (!kind[y] && getfa(x)!=getfa(y)){
z=lca(x,y); shrink(x,y,z); shrink(y,x,z);
}
}
}
return 0;
}
int main(){
int cas; scanf("%d",&cas);
while (cas--){
scanf("%d%d%d",&n,&m,&cnt); int i,j,x,y;
memset(fst,0,sizeof(fst)); tot=0;
memset(match,0,sizeof(match)); memset(pre,0,sizeof(pre));
for (i=1; i<=cnt; i++){
scanf("%d%d",&x,&y);
for (j=0; j<3; j++){
add(x,n+3*y-j); add(n+3*y-j,x);
}
}
for (i=1; i<=m; i++)
for (x=0; x<3; x++) for (y=0; y<3; y++)
if (x!=y) add(n+3*i-x,n+3*i-y);
cnt=n+m*3; int ans=0;
for (i=1; i<=cnt; i++)
if (!match[i] && bfs(i)) ans++;
printf("%d\n",ans-n);
for (i=1; i<n; i++) printf("%d ",(match[i]-n-1)/3+1);
printf("%d\n",(match
-n-1)/3+1);
}
return 0;
}


by lych
2016.3.25
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: