您的位置:首页 > 其它

Ural 1099 Work Scheduling

2016-07-18 20:33 225 查看
http://acm.timus.ru/problem.aspx?space=1&num=1099

题意:有n个人,很多对合作关系,每个人只能和一个人合作,求最多能选出多少人。

一般图匹配

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
int head,tail;
bool G[300][300],inpath[300],inqueue[300],inblossom[300];
int start,finish,father[300],base[300];
int q[300],n,match[300],newbase;
int read(){
int t=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
return t*f;
}
void init(){
int x,y;
memset(G,0,sizeof G);
n=read();
while (scanf("%d%d",&x,&y)!=EOF){
G[x][y]=G[y][x]=1;
}
}
int lca(int u,int v){
memset(inpath,0,sizeof (inpath));
while (true){
u=base[u];
inpath[u]=1;
if (u==start) break;
u=father[match[u]];
}
while (true){
v=base[v];
if (inpath[v]) break;
v=father[match[v]];
}
return v;
}
void resettrace(int u){
int v;
while (base[u]!=newbase){
v=match[u];
inblossom[base[u]]=inblossom[base[v]]=1;
u=father[v];
if (base[u]!=newbase) father[u]=v;
}
}
void blossomcontract(int u,int v){
newbase=lca(u,v);
memset(inblossom,0,sizeof (inblossom));
resettrace(u);
resettrace(v);
if (base[u]!=newbase) father[u]=v;
if (base[v]!=newbase) father[v]=u;
for (int tu=1;tu<=n;tu++)
if (inblossom[base[tu]]){
base[tu]=newbase;
if (!inqueue[tu]) q[++tail]=tu,inqueue[tu]=1;
}
}
void FindAugmentingPath(){
memset(inqueue,0,sizeof (inqueue));
memset(father,0,sizeof (father));
for (int i=1;i<=n;i++)
base[i]=i;
head=1,tail=1;q[head]=start;inqueue[start]=1;
finish=0;
while (head<=tail){
int u=q[head++];
for (int v=1;v<=n;v++)
if (G[u][v]&&(base[u]!=base[v])&&match[u]!=v){
if ((v==start)||(match[v]>0)&&(father[match[v]]>0)){
blossomcontract(u,v);
}else if (father[v]==0){
father[v]=u;
if (match[v]>0)
q[++tail]=match[v],inqueue[match[v]]=1;
else{
finish=v;
return;
}
}
}
}
}
void AugmentPath(){
int u,v,w;
u=finish;
while (u>0){
v=father[u];
w=match[v];
match[v]=u;
match[u]=v;
u=w;
}
}
void Edmonds(){
memset(match,0,sizeof match);
for (int u=1;u<=n;u++)
if (match[u]==0){
start=u;
FindAugmentingPath();
if (finish>0) AugmentPath();
}
}
void Output(){
int cnt=0;
for (int i=1;i<=n;i++)
if (match[i]>0) cnt++;
printf("%d\n",cnt);
for (int i=1;i<=n;i++)
if (i<match[i])
printf("%d %d\n",i,match[i]);
}
int main(){
init();
Edmonds();
Output();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: