您的位置:首页 > 其它

一般图最大匹配

2013-03-08 22:57 148 查看
与二分图不同,一般图的最大匹配用的是带花树开花算法。当然,本质都是寻找增广路。下面的模板是来自这个博客的 http://fanhq666.blog.163.com/blog/static/8194342620120304463580/hdu3551
#include <cstdio>
#include <algorithm>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string.h>
#include <math.h>

using namespace std;

const int N = 800;

int Next
;
int spouse
;
int belong
;

int findb(int a){
return belong[a] == a ? a : belong[a] = findb(belong[a]);
}

void together(int a,int b){
a=findb(a),b=findb(b);
if (a!=b)
belong[a]=b;
}

vector<int> E
;
int Q
,bot;
int mark
;
int visited
;
int n;

int findLCA(int x,int y){
static int t=0;
t++;
while (1){
if (x!=-1){
x=findb(x);
if (visited[x]==t)return x;
visited[x]=t;
if (spouse[x]!=-1)x=Next[spouse[x]];
else x=-1;
}
swap(x,y);
}
}

void goup(int a,int p){
while (a!=p){
int b=spouse[a],c=Next[b];
if (findb(c)!=p)Next[c]=b;
if (mark[b]==2)mark[Q[bot++]=b]=1;
if (mark[c]==2)mark[Q[bot++]=c]=1;
together(a,b);
together(b,c);
a=c;
}
}

void findaugment(int s){
for (int i=0;i<n;i++)
Next[i]=-1,belong[i]=i,mark[i]=0,visited[i]=-1;
Q[0]=s;bot=1;mark[s]=1;

for (int head=0;spouse[s]==-1 && head<bot;head++){
int x=Q[head];
for (int i=0;i<(int)E[x].size();i++){
int y=E[x][i];
if (spouse[x]!=y && findb(x)!=findb(y) && mark[y]!=2){
if (mark[y]==1){
int p=findLCA(x,y);
if (findb(x)!=p)Next[x]=y;
if (findb(y)!=p)Next[y]=x;
goup(x,p);
goup(y,p);
}else if (spouse[y]==-1){
Next[y]=x;
for (int j=y;j!=-1;){
int k=Next[j];
int l=spouse[k];
spouse[j]=k;spouse[k]=j;
j=l;
}
break;
}else{
Next[y]=x;
mark[Q[bot++]=spouse[y]]=1;
mark[y]=2;
}
}
}
}
}

pair<int, int> id
;
int D
;
int xx
, yy
;
int d
;

void build(int n1, int m)
{
for(int i = 0; i <= N; ++i)
id[i].first = -1;
n = 0;
for(int i = 0; i < m; ++i)
{
int u = xx[i], v = yy[i];
if(id[u].first == -1)
{
id[u] = make_pair(n, n + d[u] - D[u] - 1);
n += (d[u] - D[u]);
}
if(id[v].first == -1)
{
id[v] = make_pair(n, n + d[v] - D[v] - 1);
n += (d[v] - D[v]);
}
if(id[n1 + i + 1].first == -1)
{
id[n1 + i + 1] = make_pair(n, n + 1);
n += 2;
}
int t = id[n1 + i + 1].first;
E[t].push_back(t + 1);
E[t + 1].push_back(t);
for(int j = id[u].first; j <= id[u].second; ++j)
E[t].push_back(j),E[j].push_back(t);
for(int j = id[v].first; j <= id[v].second; ++j)
E[t + 1].push_back(j),E[j].push_back(t + 1);
}

}

int main()
{
int T, cas = 0;
int n1, m;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n1,&m);
memset(d,0,sizeof(d));
for(int i = 0; i < m; ++i)
{
scanf("%d %d",&xx[i],&yy[i]);
++d[xx[i]];
++d[yy[i]];
}
for(int i = 1; i <= n1; ++i)
scanf("%d",&D[i]);;
bool flag = true;
for(int i = 1; i <= n1; ++i)
{
if(d[i] < D[i])
{
flag = false;
break;
}
}
printf("Case %d: ",++cas);
if(!flag) {
puts("NO");
continue;
}
build(n1, m);

for (int i=0;i<n;i++)spouse[i]=-1;
for (int i=0;i<n;i++)
if(spouse[i] == -1)
findaugment(i);
int ans = 0;
for(int i = 0; i < n; ++i)
if(spouse[i] != -1)
++ans;
if(ans == n)
puts("YES");
else puts("NO");

for(int i = 0; i < n; ++i)
E[i].clear();
}
return 0;
}

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