zoukankan      html  css  js  c++  java
  • 网络流 poj 3436 poj 3281

    poj 3436

    一个电脑有p个部分  n 台机器

    n 个机器  每个机器 最多能服务的电脑数目 电脑进来时候需要的  0 代表一定不要 1 一定要 2可有可无    然后就是出去的电脑  0 代表没的   1代表有

    超级源点   p 部分没有1    出来的满足进去的条件   都是1      汇点 

     0   权             两点连 权值是小的         权   n+1

    跑一下Dinic

    #include<stdio.h>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<queue>
    
    using namespace std;
    
    #define MAXN 100
    #define inf  1000000000
    
    int head[MAXN];
    int z[MAXN],cnt,in[MAXN][15],out[MAXN][15],an[MAXN][MAXN],enu[MAXN*3],env[MAXN*3],enw[MAXN*3];
    struct edg
    {
        int fr,to,next,w;
    }edge[300000];
    
    void add(int u,int v,int w)
    {
        edge[cnt].fr=u;
        edge[cnt].to=v;
        edge[cnt].next=head[u];
        edge[cnt].w=w;
        head[u]=cnt++;
    }
    int st,en;
    int vis[MAXN];
    queue<int>q1;
    bool bfs()
    {
        memset(vis,-1,sizeof(vis));
        vis[st]=0;
        q1.push(st);
        while(!q1.empty())
        {
            int now = q1.front();
            q1.pop();
            for(int i=head[now];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(vis[v]<0&&edge[i].w)
                {
                    vis[v]=vis[now]+1;
                    q1.push(v);
                }
            }
        }
        return vis[en]!=-1;
    }
    int dfs(int u,int w)
    {
        if(u==en)
            return w;
        int ans=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if((vis[v]==vis[u]+1)&&edge[i].w)
            {
                int b=dfs(v,min(w-ans,edge[i].w));
                edge[i].w-=b;
                edge[i^1].w+=b;
                an[u][v]+=b;
                an[v][u]-=b;
                ans += b;
            }
        }
        return ans;
    }
    int main()
    {
        int p,n;
        scanf("%d%d",&p,&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&z[i]);
            for(int j=1;j<=p;j++)
                scanf("%d",&in[i][j]);
            for(int j=1;j<=p;j++)
                scanf("%d",&out[i][j]);
        }
        st =0;
        en =n+1;
        cnt=0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=n;i++)
        {
            int ok=0;
            for(int j=1;j<=p;j++)
                if(in[i][j]==1)
                    ok=1;
            if(ok==0)
            {
                add(st,i,z[i]);
                add(i,st,0);
            }
            ok=0;
            for(int j=1;j<=p;j++)
                ok+=out[i][j];
            if(ok==p)
            {
                add(i,en,z[i]);
                add(en,i,0);
            }
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                    continue;
                //进去出来建边
                int ok=0;
                for(int k=1;k<=p;k++)
                    if(out[i][k]+in[j][k]==1)
                        ok=1;
                if(ok==0)
                {
                    add(i,j,min(z[i],z[j]));
                    add(j,i,0);
                }
            }
        }
        int ans=0;
        while(bfs())
            ans += dfs(st,inf);
        if(ans==0)
            printf("0 0
    ");
        else
        {
            int cn=0;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(an[i][j]>0)
                    {
                        enu[cn]=i;
                        env[cn]=j;
                        enw[cn]=an[i][j];
                        cn++;
                    }
            printf("%d %d
    ",ans,cn);
            for(int i=0;i<cn;i++)
                printf("%d %d %d
    ",enu[i],env[i],enw[i]);
        }
        return 0;
    }
    View Code

    n 个牛 F个吃的   D个喝的

    一个牛 只能有1个吃的和喝的  一个吃的 只能给一个牛  喝的也是

    问 多少牛 有吃的也有喝的 

    一开始 建图 超级原点  吃的   牛  喝的 超级汇点  

    结果 GG了  因为这样 有2个吃的  2个喝的 都满足牛  答案是2 

    所以 牛要拆一下 超级源点   吃的      牛  牛     喝的  超级汇点

    权值            1    条件+权值  1  条件+权值  1

    #include<stdio.h>
    #include<algorithm>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<vector>
    #include<queue>
    
    using namespace std;
    
    #define MAXN 410
    #define inf  1000000000
    
    int head[MAXN];
    int cnt,S,T;
    struct edg
    {
        int to,w,next;
    }edge[200000];
    void add(int u,int to,int w)
    {
        edge[cnt].to=to;
        edge[cnt].w=w;
        edge[cnt].next=head[u];
        head[u]=cnt++;
    }
    queue<int>q1;
    int vis[MAXN];
    
    bool bfs()
    {
        memset(vis,-1,sizeof(vis));
        vis[S]=0;
        q1.push(S);
        while(!q1.empty())
        {
            int now=q1.front();
            q1.pop();
            for(int i=head[now];i!=-1;i=edge[i].next)
            {
                int v=edge[i].to;
                if(vis[v]<0&&edge[i].w)
                {
                    vis[v]=vis[now]+1;
                    q1.push(v);
                }
            }
        }
        return vis[T]!=-1;
    }
    int dfs(int u,int w)
    {
        if(u==T)
            return w;
        int ans=0;
    
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if((vis[v]==vis[u]+1)&&edge[i].w)
            {
                int b=dfs(v,min(edge[i].w,w-ans));
                edge[i].w-=b;
                edge[i^1].w+=b;
                ans += b;
            }
        }
        //printf("%d
    ",ans);
        return ans;
    }
    int main()
    {
        int n,f,d;
        scanf("%d%d%d",&n,&f,&d);
        memset(head,-1,sizeof(head));
        cnt=0;
        S=0;
        T=n*2+f+d+1;
        for(int i=1;i<=f;i++)
        {
            add(S,i,1);
            add(i,S,0);
        }
        for(int i=n*2+f+1;i<=n*2+f+d;i++)
        {
            add(i,T,1);
            add(T,i,0);
        }
        for(int i=f+1;i<=n+f;i++)
        {
            add(i,i+n,1);
            add(i+n,i,0);
        }
        for(int i=1;i<=n;i++)
        {
            int f1,d1;
            scanf("%d%d",&f1,&d1);
            for(int j=1;j<=f1;j++)
            {
                int a;
                scanf("%d",&a);
                add(a,i+f,1);
                add(i+f,a,0);
            }
            for(int j=1;j<=d1;j++)
            {
                int a;
                scanf("%d",&a);
                add(i+f+n,a+n*2+f,1);
                add(a+n*2+f,i+f+n,0);
            }
        }
        int ans=0;
        while(bfs())
            ans += dfs(S,inf);
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    接口测试之Postman简介
    postman发送get请求
    postman添加权限验证
    接口测试基础
    postman发送post请求
    postman测试上传文件
    1 R语言介绍
    《荣枯鉴》明鉴卷六
    《荣枯鉴》节仪卷五
    《荣枯鉴》交结卷四
  • 原文地址:https://www.cnblogs.com/cherryMJY/p/6545097.html
Copyright © 2011-2022 走看看