2013-team4/code/blossom
从 Trac 迁移的文章
这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。
原文章内容如下:
{{{
一般图匹配算法,时间复杂度O(N^3)
}}}
{{{
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=300;
vector<int> E[MAXN];
queue<int> q;
int map[MAXN][MAXN];
int next[MAXN], match[MAXN], fa[MAXN];
int mark[MAXN], vis[MAXN];
int N;
int getf(int x)
{
if (x!=fa[x]) fa[x]=getf(fa[x]);
return fa[x];
}
void Union(int a, int b)
{
a=getf(a), b=getf(b);
if (a!=b) fa[a]=b;
}
int LCA(int x, int y)
{
static int t=0; t++;
while (1)
{
if (x!=-1)
{
x=getf(x);
if (vis[x]==t) return x;
vis[x]=t;
if (match[x]!=-1) x=next[match[x]];
else x=-1;
}
swap(x, y);
}
}
void group(int a, int p)
{
while (a!=p)
{
int b=match[a], c=next[b];
if (getf(c)!=p) next[c]=b;
if (mark[b]==2) mark[b]=1, q.push(b);
if (mark[c]==2) mark[c]=1, q.push(c);
Union(a, b); Union(b, c); a=c;
}
}
void findpath(int s)
{
for (int i=0; i<N; i++) next[i]=-1, fa[i]=i, mark[i]=0, vis[i]=-1;
while (!q.empty()) q.pop();
q.push(s); mark[s]=1;
while (match[s]==-1&&!q.empty())
{
int x=q.front(); q.pop();
for (int i=0; i<(int)E[x].size(); i++)
{
int y=E[x][i];
if (match[x]!=y&&getf(x)!=getf(y)&&mark[y]!=2)
{
if (mark[y]==1)
{
int p=LCA(x, y);
if (getf(x)!=p) next[x]=y;
if (getf(y)!=p) next[y]=x;
group(x, p); group(y, p);
}
else if (match[y]==-1)
{
next[y]=x;
for (int j=y; j!=-1;)
{
int k=next[j], l=match[k];
match[j]=k; match[k]=j;
j=l;
}
break;
}
else
{
next[y]=x; q.push(match[y]);
mark[match[y]]=1; mark[y]=2;
}
}
}
}
}
int main()
{
scanf("%d", &N);
memset(map, 0, sizeof(map));
int x, y;
while (scanf("%d%d", &x, &y)!=EOF) map[x-1][y-1]=map[y-1][x-1]=1;
for (int i=0; i<N; i++)
{
E[i].clear();
for (int j=0; j<N; j++)
{
if (j==i||!map[i][j]) continue;
E[i].push_back(j);
}
}
memset(match, -1, sizeof(match));
for (int i=0; i<N; i++)
if (match[i]==-1) findpath(i);
int ret=0;
for (int i=0; i<N; i++) if (match[i]!=-1) ret++;
printf("%d\n", ret);
for (int i=0; i<N; i++)
if (match[i]!=-1&&match[i]>i) printf("%d %d\n", i+1, match[i]+1);
return 0;
}
}}}
一般图匹配算法,时间复杂度O(N^3)
#include <queue>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=300;
vector<int> E[MAXN];
queue<int> q;
int map[MAXN][MAXN];
int next[MAXN], match[MAXN], fa[MAXN];
int mark[MAXN], vis[MAXN];
int N;
int getf(int x)
{
if (x!=fa[x]) fa[x]=getf(fa[x]);
return fa[x];
}
void Union(int a, int b)
{
a=getf(a), b=getf(b);
if (a!=b) fa[a]=b;
}
int LCA(int x, int y)
{
static int t=0; t++;
while (1)
{
if (x!=-1)
{
x=getf(x);
if (vis[x]==t) return x;
vis[x]=t;
if (match[x]!=-1) x=next[match[x]];
else x=-1;
}
swap(x, y);
}
}
void group(int a, int p)
{
while (a!=p)
{
int b=match[a], c=next[b];
if (getf(c)!=p) next[c]=b;
if (mark[b]==2) mark[b]=1, q.push(b);
if (mark[c]==2) mark[c]=1, q.push(c);
Union(a, b); Union(b, c); a=c;
}
}
void findpath(int s)
{
for (int i=0; i<N; i++) next[i]=-1, fa[i]=i, mark[i]=0, vis[i]=-1;
while (!q.empty()) q.pop();
q.push(s); mark[s]=1;
while (match[s]==-1&&!q.empty())
{
int x=q.front(); q.pop();
for (int i=0; i<(int)E[x].size(); i++)
{
int y=E[x][i];
if (match[x]!=y&&getf(x)!=getf(y)&&mark[y]!=2)
{
if (mark[y]==1)
{
int p=LCA(x, y);
if (getf(x)!=p) next[x]=y;
if (getf(y)!=p) next[y]=x;
group(x, p); group(y, p);
}
else if (match[y]==-1)
{
next[y]=x;
for (int j=y; j!=-1;)
{
int k=next[j], l=match[k];
match[j]=k; match[k]=j;
j=l;
}
break;
}
else
{
next[y]=x; q.push(match[y]);
mark[match[y]]=1; mark[y]=2;
}
}
}
}
}
int main()
{
scanf("%d", &N);
memset(map, 0, sizeof(map));
int x, y;
while (scanf("%d%d", &x, &y)!=EOF) map[x-1][y-1]=map[y-1][x-1]=1;
for (int i=0; i<N; i++)
{
E[i].clear();
for (int j=0; j<N; j++)
{
if (j==i||!map[i][j]) continue;
E[i].push_back(j);
}
}
memset(match, -1, sizeof(match));
for (int i=0; i<N; i++)
if (match[i]==-1) findpath(i);
int ret=0;
for (int i=0; i<N; i++) if (match[i]!=-1) ret++;
printf("%d\n", ret);
for (int i=0; i<N; i++)
if (match[i]!=-1&&match[i]>i) printf("%d %d\n", i+1, match[i]+1);
return 0;
}