Problema del esquema de coincidencia del piloto Luogu P2756 (flujo máximo que busca la coincidencia máxima del gráfico bipartito)

enlace

Tema: Encuentre la máxima coincidencia de un gráfico bipartito

Idea: la coincidencia máxima de gráficos bipartitos tiene un algoritmo húngaro, pero también se puede resolver mediante flujo de red. Establecemos el punto establecido en el lado izquierdo del gráfico bipartito en A, y el punto establecido en el lado derecho del gráfico bipartito en B. Conectamos un borde dirigido de A a B, y el peso del borde es 1. Establecemos una superfuente y un superdrenaje. La súper fuente conecta el borde dirigido al conjunto A y el conjunto B conecta el borde dirigido al súper fregadero (el peso del borde es 1). Utilice el algoritmo dinic para encontrar el flujo máximo. El flujo máximo es la máxima coincidencia, y el borde coincidente es el borde cuyo flujo no es 0 entre los bordes delanteros.

código:

#include <bits/stdc++.h>
#define ll long long
#define pi pair<int,int>
#define mk make_pair
#define pb push_back
using namespace std;

const int maxn = 105 inf = 2e9+10000;
 
struct Edge{
    
    
    int from,to,cap,flow;
};
 
 
struct Dinic{
    
    
    int n,m,s,t;
    vector<Edge>edges;
    vector<int>g[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];
    void init(int n)
    {
    
    
        this->n=n;
        for(int i=0;i<=n;i++)g[i].clear();
        edges.clear();
    }
    void AddEdge(int from,int to,int cap)
    {
    
    
        edges.push_back((Edge){
    
    from,to,cap,0});
        edges.push_back((Edge){
    
    to,from,0,0});
        m=edges.size();
        g[from].push_back(m-2);
        g[to].push_back(m-1);
    }
    bool BFS()
    {
    
    
    	memset(vis,0,sizeof(vis));
        queue<int>q;
        q.push(s);
        d[s]=0;
        vis[s]=1;
        while(!q.empty())
        {
    
    
            int x=q.front();
            q.pop();
            for(int i=0;i<g[x].size();i++)
            {
    
    
                Edge& e=edges[g[x][i]];
                if(!vis[e.to]&&e.cap>e.flow)
                {
    
    
                    vis[e.to]=1;
                    d[e.to]=d[x]+1;
                    q.push(e.to);
                }
            }
        }
        return vis[t];
    }
    int DFS(int x,int a)
    {
    
    
        if(x==t||a==0)return a;
        int flow=0,f;
        for(int& i=cur[x];i<g[x].size();i++)
        {
    
    
            Edge& e=edges[g[x][i]];
            if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0)
            {
    
    
                e.flow+=f;
                edges[g[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0)break;
            }
        }
        return flow;
    }
    
    int Maxflow(int s,int t,int need)
    {
    
    
        this->s=s;
        this->t=t;
        int flow=0;
        while(BFS())
        {
    
    
        	memset(cur,0,sizeof(cur));
            flow+=DFS(s,inf);
            if(flow>=need)return flow;
        }
        return flow;
    }
    
    vector<int> Mincut()
    {
    
    
        vector<int>ans;
        for(int i=0;i<edges.size();i++)
        {
    
    
            Edge& e=edges[i];
            if(vis[e.from]&&!vis[e.to]&&e.cap>0)
                ans.push_back(i);
        }
        return ans;
    }
    void Reduce()
    {
    
    
        for(int i=0;i<edges.size();i++)
            edges[i].cap-=edges[i].flow;
    }
    void ClearFlow()
    {
    
    
        for(int i=0;i<edges.size();i++)
            edges[i].flow=0;
    }
}sol;


int main()
{
    
    
	int m,n;
	scanf("%d%d",&m,&n);
	int u,v;
	while(~scanf("%d%d",&u,&v))
	{
    
    
		if(u == -1)break;
		sol.AddEdge(u,v,1);
	}
	int s = n+1;
	int t = s+1;
	for(int i=1;i<=m;i++) {
    
    
		sol.AddEdge(s,i,1);
	}
	for(int i=m+1;i<=n;i++) {
    
    
		sol.AddEdge(i,t,1);
	}
	
	int ans = sol.Maxflow(s,t,inf);
	printf("%d\n",ans);
	for(int i=0;i<sol.edges.size();i++)
	{
    
    
		if(sol.edges[i].from <= m && sol.edges[i].flow > 0)printf("%d %d\n",sol.edges[i].from,sol.edges[i].to);
	}
	return 0;
 } 

Supongo que te gusta

Origin blog.csdn.net/weixin_44499508/article/details/107142022
Recomendado
Clasificación