Gráfico general coincidencia máxima (con árbol de flores)

Árbol con flores

El núcleo del algoritmo de Hungría es encontrar Zengguang Road.
Sin embargo, en el gráfico general, debido a que hay anillos extraños, cuando se busca Zengguang Road, puede rodear un anillo extraño y luego pasar el mismo borde varias veces, por lo que no puede directamente Hungría.
Tenga en cuenta que para un anillo impar, debe haber al menos un punto que coincida con el exterior del anillo, por lo que podemos considerar reducir el anillo impar a un punto (floración).
Considere bfs y coloree los nodos en blanco y negro. Suponiendo que el punto de partida es un punto negro, solo se almacenan puntos negros en la cola.
Obviamente, el borde negro-> blanco es un borde no coincidente, y el borde blanco-> negro es un borde coincidente.
Atravesamos el punto de salida \ (v \) del punto negro \ (u \) del equipo actual . Si \ (v \) no está manchado, lo teñiremos de blanco. Si \ (v \) ya coincide, entonces tiñe de negro su punto correspondiente y únete a la cola. De lo contrario, encontraremos una manera de aumentar. Si \ (v \) es un punto blanco, entonces hemos encontrado un anillo par, que no tiene ningún efecto en la coincidencia y puede ignorarse directamente. Si \ (v \) es un punto negro, entonces encontramos un anillo extraño, encontramos la lca de estos dos puntos en el árbol bfs y luego florecemos. Debido a que el anillo impar es un punto negro después de la floración, el punto blanco del anillo debe cambiarse a un punto negro y agregarse a la cola. Generalmente usamos el conjunto de verificación para registrar en qué flor se encuentra cada punto. Al mismo tiempo, para poder caminar de regreso a lo largo de Zengguang Road, necesitamos registrar un \ (pre \) que indique el precursor de este punto. \ (Pre \) en el borde no coincidente de la flor







Es bidireccional, un poco como una lista doblemente vinculada, y debe procesarse cuando se reduce.

#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<numeric>
#include<algorithm>
const int N=507;
int n,fa[N],col[N],mat[N],pre[N];std::vector<int>e[N];std::queue<int>q;
int read(){int x;scanf("%d",&x);return x;}
int find(int x){return x==fa[x]? x:fa[x]=find(fa[x]);}
int lca(int u,int v)
{
    static int f[N],t;++t;
    for(;f[u]^t;std::swap(u,v)) if(u) f[u]=t,u=find(pre[mat[u]]);
    return u;
}
void blossum(int u,int v,int p){for(;find(u)^p;u=pre[v]) if(pre[u]=v,v=mat[u],fa[u]=fa[v]=p,col[v]==1) col[v]=2,q.push(v);}
int bfs(int s)
{
    while(!q.empty()) q.pop();
    memset(col+1,0,n<<2),std::iota(fa+1,fa+n+1,1),q.push(s),col[s]=2;
    while(!q.empty())
    {
	int u=q.front(),p;q.pop();
	for(int v:e[u])
	    if(!col[v])
	    {
		col[v]=1,pre[v]=u,col[mat[v]]=2,q.push(mat[v]);
		if(!mat[v])
		{
		    while(u) u=mat[pre[v]],mat[v]=pre[v],mat[pre[v]]=v,v=u;
		    return 1;
		}
	    }
	    else if(col[v]==2) p=lca(u,v),blossum(u,v,p),blossum(v,u,p);
    }
    return 0;
} 
int main()
{
    n=read();int m=read(),ans=0;
    for(int i=1,u,v;i<=m;++i) u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
    for(int i=1;i<=n;++i) if(!mat[i]&&bfs(i)) ++ans;
    printf("%d\n",ans);
    for(int i=1;i<=n;++i) printf("%d ",mat[i]);
}

Supongo que te gusta

Origin www.cnblogs.com/cjoierShiina-Mashiro/p/12717850.html
Recomendado
Clasificación