您的位置:首页 > 其它

URAL 1099 一般图带花树匹配

2016-06-09 16:30 381 查看
点击打开链接

题意:给n个人和许多关系,问能够匹配的人数和匹配的人

思路:据说是带花树的模版题,来练一练,原理什么的根本不是本弱可以理解的,权当是一个模版直接用算了,就像最大流一样,而且据本弱做的一些弱题发现这种题目考验的是建图的能力,也就是上边的所有的模版几乎不会动,然后直接建好图就行了,说白了就是太弱看不懂原理直接当模版使了#include <queue>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3fll;
const int maxn=230;
int f[maxn],spouse[maxn],Next[maxn],Q[maxn],mark[maxn],vis[maxn];
int n,bot;
vector<int>G[maxn];
int find1(int x){
if(x!=f[x]) f[x]=find1(f[x]);
return f[x];
}
void unite(int a,int b){
int aa=find1(a);
int bb=find1(b);
if(aa==bb) return ;
f[aa]=bb;
}
int findLCA(int x,int y){
static int t=0;
t++;
while(1){
if(x!=-1){
x=find1(x);
if(vis[x]==t) return x;
vis[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(find1(c)!=p) Next[c]=b;
if(mark[b]==2) mark[Q[bot++]=b]=1;
if(mark[c]==2) mark[Q[bot++]=c]=1;
unite(a,b);unite(b,c);a=c;
}
}
void findaugment(int s){
for(int i=0;i<n;i++) Next[i]=-1,f[i]=i,mark[i]=0,vis[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(unsigned int i=0;i<G[x].size();i++){
int y=G[x][i];
if(spouse[x]!=y&&find1(x)!=find1(y)&&mark[y]!=2){
if(mark[y]==1){
int p=findLCA(x,y);
if(find1(x)!=p) Next[x]=y;
if(find1(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;
}
}
}
}
}
int num[maxn][maxn];
int main(){
scanf("%d",&n);
int x,y;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++) num[i][j]=0;
}
while(scanf("%d%d",&x,&y)!=EOF){
x--;y--;
if(x!=y&&num[x][y]==0){
num[x][y]=num[y][x]=1;
G[x].push_back(y);
G[y].push_back(x);
}
}
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++;
printf("%d\n",ans);
for(int i=0;i<n;i++){
if(spouse[i]!=-1&&spouse[i]>i) printf("%d %d\n",i+1,spouse[i]+1);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图论 匹配