题意:给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; }
时间: 2024-10-07 03:15:30