中文题面不解释,为了留一个板子写的,尽量在理解了,不是很容易啊。。这个算法很是精妙,贴几个链接方便复习。。不经常碰到总是会忘记的。
看了其他大佬的博客一点点照着习惯改的。。还写了点备注什么的。。看不懂戳下面。。
https://blog.csdn.net/qq_36797743/article/details/60968291
https://www.cnblogs.com/zhsl/p/3271754.html
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
using namespace std;
typedef long long ll;
const int maxm=124752*2;
const int maxn=505*2;
int to[maxm],nex[maxm],head[maxn],cnt;
int n,m,fa[maxn];
int link[maxn];//表示最终匹配了哪个点
int match[maxn];//寻找增广路用的父亲
int id[maxn];
//标示这个点的类型 -1未访问 0为S点 1为T点
int road[maxn]; //记录当前的一整条增广路
int tmplink[maxn]; //存储暂时相连的点
int ti; //寻找lca时打的标记
int vis[maxn];//找lca时判断是否为同一次查找
void add(int u,int v){
to[cnt]=v,nex[cnt]=head[u];
head[u]=cnt++;
}
int fin(int x){
return fa[x]==x?x:fa[x]=fin(fa[x]);
}
int lca(int x,int y){ //去找lca
//这里的lca的意思是 S点找到S点
//肯定是在第二次找S点的时候找到了一个也在这个点开始搜到的点
//如1->2 1->3 那么2在找到3的时候是从1延伸出来的 lca就是这个点1
ti++;
while(vis[x]!=ti){
if(x!=0){
x=fin(x); //并查集找到这个花的根
//一个奇环被缩成一个点之后 就只当成一朵花
//这个点就是这朵花的根
if(vis[x]==ti) return x; //如果就是这次寻找的
vis[x]=ti;
if(link[x]!=0) x=fin(tmplink[link[x]]);
//如果x有连接 那么就去找这个点原来连接上的点的暂时存储的点
//即不断地向上爬 去找它的根
else x=0;
//否则换个点进行寻找
}
swap(x,y);
}
return x;
}
int st,ed;
//对环进行特殊化处理 表示点x和点y相撞 并且是从k衍生的
void Change(int x,int y,int k){
while(fin(x)!=k){
tmplink[x]=y;
int z=link[x];
id[z]=0; road[ed++]=z; if(ed>=maxn-1) ed=1;
if(fin(z)==z) fa[z]=k;
if(fin(x)==x) fa[x]=k;
y=z; x=tmplink[y];
}
}
//开始对点u进行增广
void deal(int u){
for(int i=1;i<=n;i++){
fa[i]=i; id[i]=-1;
}
st=1,ed=2;// 增广路的开始和结束
road[st]=u; id[u]=0;
while(st!=ed){
int x=road[st];
for(int i=head[x];~i;i=nex[i]){
int v=to[i];
if(!link[v]&&v!=u){
//如果v没有被匹配,那么就把这条路上的点全部反一反进行标记
tmplink[v]=x;
int last,now=v,tmp;
while(now){
//让tmp为now暂时存的那个点
//last是原来tmp的匹配点
//要把tmp和now连接,并把now变成last进行重复操作
//总的来说就是now强抢了tmp tmp原来匹配的点没办法只能去找其他点
tmp=tmplink[now];
last=link[tmp];
link[tmp]=now; link[now]=tmp;
now=last;
}
return ;
}
if(id[v]==-1){ //该点还未被访问过 尝试进行增广
id[v]=1;
tmplink[v]=x;
id[link[v]]=0; road[ed++]=link[v];
if(ed>=maxn-1) ed=1;
}
else if(id[v]==0&&fin(x)!=fin(v)){
int f=lca(x,v);
Change(x,v,f);
Change(v,x,f);
}
}
st++;
if(st>=maxn-1) st-1;
}
}
int main(){
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
rep(i,1,m){
int x,y;
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
int ans=0;
rep(i,1,n)
if(!link[i])
deal(i);
rep(i,1,n) if(link[i]) ans++;
printf("%d\n",ans/2);
rep(i,1,n){
printf("%d%c",link[i],i==n?'\n':' ');
}
return 0;
}