Prime Game Gym - 101981J (network flow / bipartite graph)

If the network flow best practice built edge
of m points dividing flow restrictor
to establish a starting point for connecting two points, but wherein n is connected to a flow is a inf k is
then linked up nm maximum flow can run

Bipartite graph to nm of the side construction 2 times (note apart n 'is a new node)
run bipartite graph when the attention sequence, start and original node n rerun after the new n nodes
as to ensure that the priority is not expanded stream (without k)
but that there may be a case where the flow rate of the other side will be
the maximum flow rate so after finish bipartite graph to determine what the original n points can be used
in the available maximum flow + k with the bipartite graph results can take min

网络流
#include<bits/stdc++.h>

using namespace std;

#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define inf 0x3f3f3f3f

const int maxn=5e6+10;

struct edge{
    int u,v,w,next;
}e[maxn*2];

int n,m,k,maxflow,dep[maxn*2],tot=-1,g[maxn*2];

void creatEdge(int u,int v,int w)
{
    e[++tot]=(edge){u,v,w,g[u]};
    g[u]=tot;
}

int bfs(int s,int t)
{
    queue<int>q;
    mem(dep,-1);
    dep[s]=0;
    q.push(s);
    while(!q.empty())
    {
        int now=q.front();
        q.pop();
        for(int i=g[now];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(dep[v]==-1&&e[i].w)
            {
                dep[v]=dep[now]+1;
                q.push(v);
            }
        }
    }
    return dep[t]==-1?0:1;
}

int dfs(int s,int t,int lim)
{
    if(!lim||s==t) return lim;
    int flow=0,f;
    for(int i=g[s];i!=-1;i=e[i].next)
    {
        int v=e[i].v,w=e[i].w;
        if(dep[v]==dep[s]+1&&(f=dfs(v,t,min(lim,w))))
        {
            flow+=f;
            lim-=f;
            e[i].w-=f;
            e[i^1].w+=f;
            if(!lim) break;
        }
    }
    return flow;
}

void Dinic(int s,int t)
{
    int tot=0;
    while(bfs(s,t))
        maxflow+=dfs(s,t,inf);
}

int main()
{
    int s,t;
    mem(g,-1);
    cin>>n>>m>>k;

    int tp=n+m;
    for(int i=1;i<=n;i++)
    {
        int tt;
        cin>>tt;
        for(int j=1;j<=tt;j++)
        {
            int v;
            cin>>v;
            creatEdge(2*m+i,v,1);
            creatEdge(v,2*m+i,0);
        }
    }
    int pos=4*500+1;
    for(int i=1;i<=m;i++)
    {
        creatEdge(i,i+m,1);
        creatEdge(i+m,i,0);

        creatEdge(i+m,pos+1,1);
        creatEdge(pos+1,i+m,0);

    }

    for(int i=1;i<=n;i++)
    {
        creatEdge(pos+2,2*m+i,1);
        creatEdge(2*m+i,pos+2,0);

        creatEdge(pos+3,2*m+i,1);
        creatEdge(2*m+i,pos+3,0);
    }
    creatEdge(pos+4,pos+3,500);
    creatEdge(pos+3,pos+4,0);

    creatEdge(pos+4,pos+2,k);
    creatEdge(pos+2,pos+4,0);


    s=pos+4,t=pos+1;
    Dinic(s,t);
//    cout<<s<<" "<<t<<endl;
    cout<<maxflow<<endl;
    return 0;
}
二分图
#include<bits/stdc++.h>
using namespace std;

const int maxn=6e5+10;

struct node{
    int u,v,next;
}e[maxn];

int n,m,k,temp;
int g[maxn],vis[maxn],xM[maxn],yM[maxn],tot=0;
int chk[maxn];

void make(int u,int v)
{
    e[++tot]={u,v,g[u]};
    g[u]=tot;
}

int searchpath(int u)
{
    for(int i=g[u];i;i=e[i].next)
    {
        int v=e[i].v;
        if(!chk[v])
        {
            chk[v]=1;
            if(yM[v]==-1||searchpath(yM[v]))
            {
                yM[v]=u;
                xM[u]=v;
                return 1;
            }
        }
    }
    return 0;
}

int Maxmatch()
{
    int u,ret=0;
    memset(xM,-1,sizeof(xM));
    memset(yM,-1,sizeof(yM));
    for(u=m+1;u<=temp;u++)
    {
        if(xM[u]==-1)
        {
            memset(chk,0,sizeof(chk));
            if(searchpath(u)) ret++;
        }
    }
    return ret;
}

int main(){
    cin>>n>>m>>k;
    temp=m;
    for(int i=1;i<=n;i++)
    {
        int t;
        cin>>t;
        temp++;
        for(int j=1;j<=t;j++)
        {
            int now;
            cin>>now;
            make(temp,now);
            make(temp+n,now);
        }
    }
    temp+=n;
    int ans=Maxmatch();
    int tt=0;
    for(int u=m+1;u<=m+n;u++)
       if(xM[u]!=-1) tt++;
   cout<<min(ans,tt+k)<<endl;
    return 0;
}

Guess you like

Origin www.cnblogs.com/minun/p/11564775.html