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
  • 相关阅读:
    78. Subsets
    93. Restore IP Addresses
    71. Simplify Path
    82. Remove Duplicates from Sorted List II
    95. Unique Binary Search Trees II
    96. Unique Binary Search Trees
    312. Burst Balloons
    程序员社交平台
    APP Store开发指南
    iOS框架搭建(MVC,自定义TabBar)--微博搭建为例
  • 原文地址:https://www.cnblogs.com/cherryMJY/p/6545097.html
Copyright © 2011-2022 走看看