一般图匹配问题,用带花树算法
这个直接套模板即可,光是模板也够长了,这次就先知道这个算法了,以后再深究
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int N=250;
int n;
bool gap[N][N];
int match[N];
bool inque[N],inpath[N],inblo[N];
int head,tail;
int que[N];
int start,finish;
int newbase;
int father[N],base[N];
int cnt;
void push(int u)
{
que[tail]=u;
tail++;
inque[u]=true;
}
int pop()
{
int res=que[head];
head++;
return res;
}
int FCA(int u,int v)
{
memset(inpath,false,sizeof(inpath));
while(true)
{
u=base[u];
inpath[u]=true;
if(u==start) break;
u=father[match[u]];
}
while(true)
{
v=base[v];
if(inpath[v]) break;
v=father[match[v]];
}
return v;
}
void RT(int u)
{
int v;
while(base[u]!=newbase)
{
v=match[u];
inblo[base[u]]=inblo[base[v]]=true;
u=father[v];
if(base[u]!=newbase) father[u]=v;
}
}
void BC(int u,int v)
{
newbase=FCA(u,v);
memset(inblo,false,sizeof(inblo));
RT(u);
RT(v);
if(base[u]!=newbase) father[u]=v;
if(base[v]!=newbase) father[v]=u;
for(int tu=1;tu<=n;tu++)
if(inblo[base[tu]])
{
base[tu]=newbase;
if(!inque[tu]) push(tu);
}
}
void FAP()
{
memset(inque,false,sizeof(inque));
memset(father,0,sizeof(father));
for(int i=1;i<=n;i++)
base[i]=i;
head=tail=1;
push(start);
finish=0;
while(head<tail)
{
int u=pop();
for(int v=1;v<=n;v++)
if(gap[u][v]&&(base[u]!=base[v])&&(match[u]!=v))
{
if((v==start)||((match[v]>0)&&father[match[v]]>0))
BC(u,v);
else if(father[v]==0)
{
father[v]=u;
if(match[v]>0)
push(match[v]);
else
{
finish=v;
return;
}
}
}
}
}
void AP()
{
int u,v,w;
u=finish;
while(u>0)
{
v=father[u];
w=match[v];
match[v]=u;
match[u]=v;
u=w;
}
}
void ED()
{
memset(match,0,sizeof(match));
for(int u=1;u<=n;u++)
if(match[u]==0)
{
start=u;
FAP();
if(finish>0) AP();
}
}
int main()
{
int u,v;
memset(gap,false,sizeof(gap));
scanf("%d",&n);
while(~scanf("%d%d",&u,&v))
gap[u][v]=gap[v][u]=true;
ED();
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(match[i]>i) printf("%d %d\n",i,match[i]);
return 0;
}