zoukankan      html  css  js  c++  java
  • Prime Game Gym

    网络流做法最要是建边
    将m点分割限流
    建立一个起点 连接2个点在于n相连 不过一个流量是inf 一个是k
    再把n m连起来 跑最大流即可

    二分图把 n m的边建2遍(注意开的n'是一个新的节点)
    跑二分图的时候注意顺序,先跑原本的n的节点 再跑之后新建的n个节点
    因为要保证优先不扩流(不用k)
    但这样有可能会出现用别的边的流量的情况出现
    所以在跑完二分图之后 判断一下原本的n个点可以用的最大流量
    在 可用的最大流量+k 与 二分图结果 取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;
    }
    
  • 相关阅读:
    打印空心字符菱形
    良好的布局与风格
    编写递归函数来使字符串逆序
    排序函数重载
    easyui刷新当前页
    Easyui 翻页不保存选中记录
    HTML 字体颜色 色号对照表
    SpringMVC结合ajaxfileupload.js实现文件无刷新上传
    ajax如何传递参数给controller
    eclipse启动tomcat无法访问的解决方法
  • 原文地址:https://www.cnblogs.com/minun/p/11564775.html
Copyright © 2011-2022 走看看