• 网络流24题——试题库问题 luogu 2763


    题目描述看:这里

    这是我们遇到的第一个要求输出方案的问题

    考虑建图然后用最大流思想:

    首先由源点向每一道试题连边,容量为1

    然后由每一种试题类型向汇点连边,容量为需求量

    最后由每一道试题向可能属于的试题类型连边,容量为1

    然后跑最大流,如果流量等于总需求量的话即证明合法(每一条到汇点的边流量都跑满才能使流量等于总需求量,这时一定是合法的)

    接下来考虑在合法时如何输出方案

    根据网络流的特征,我们可以发现如果某一道试题被归入了某一个类型,那么这道试题到这个类型的边就会跑上1的流量

    而如果正向边跑上了1的流量,正向边的容量即变为0,而反向边的容量即成为1

    所以我们仅需检验正向边容量为0/反向边容量为1任意一个条件,即可说明这道试题归属到了这个试题类型中

    考虑到是按试题类型输出选择的试题编号,所以我们检验反向边更加简单一些

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    using namespace std;
    const int inf=0x3f3f3f3f;
    struct Edge
    {
        int next;
        int to;
        int val;
    }edge[40005];
    int head[1505];
    int dis[1505];
    int cur[1505];
    int k,n;
    int cnt=1;
    int st,ed;
    void init()
    {
        memset(head,-1,sizeof(head));
        cnt=1;
    }
    void add(int l,int r,int w)
    {
        edge[cnt].next=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    bool bfs()
    {
        memcpy(cur,head,sizeof(head));
        memset(dis,0,sizeof(dis));
        dis[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int to=edge[i].to;
                if(!dis[to]&&edge[i].val)dis[to]=dis[u]+1,M.push(to);
            }
        }
        return dis[ed];
    }
    int ide(int x)
    {
        return (x&1)?x+1:x-1;
    }
    int dfs(int x,int lim)
    {
        if(x==ed)return lim;
        int ret=0;
        for(int i=head[x];i!=-1;i=edge[i].next)
        {
            int to=edge[i].to;
            if(edge[i].val&&dis[to]==dis[x]+1)
            {
                int temp=dfs(to,min(lim,edge[i].val));
                if(temp)
                {
                    edge[i].val-=temp;
                    edge[ide(i)].val+=temp;
                    lim-=temp;
                    ret+=temp;
                    if(!lim)break;
                }
            }
            cur[x]=i;
        }
        return ret;
    }
    int dinic()
    {
        int ret=0;
        while(bfs())ret+=dfs(st,inf);
        return ret;
    }
    int main()
    {
        scanf("%d%d",&k,&n);
        init();
        st=k+n+1,ed=k+n+2;
        int s=0;
        for(int i=1;i<=k;i++)
        {
            int x;
            scanf("%d",&x);
            s+=x;
            add(i+n,ed,x);
            add(ed,i+n,0);
        }
        for(int i=1;i<=n;i++)
        {
            int num;
            scanf("%d",&num);
            for(int j=1;j<=num;j++)
            {
                int x;
                scanf("%d",&x);
                add(i,x+n,1);
                add(x+n,i,0);
            }
            add(st,i,1);
            add(i,st,0);
        }
        int t=dinic();
        if(t!=s)printf("No Solution!
    ");
        else
        {
            for(int i=1;i<=k;i++)
            {
                printf("%d: ",i);
                for(int j=head[i+n];j!=-1;j=edge[j].next)
                {
                    if(edge[j].to!=ed&&edge[j].val==1)printf("%d ",edge[j].to);
                }
                printf("
    ");
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    Windows 任务调度程序定时执行Python脚本
    sklearn 学习 第三篇:knn分类
    sklearn 学习 第二篇:特征预处理
    sklearn 学习 第一篇:分类
    DAX 第六篇:统计函数(描述性统计)
    DAX 第四篇:CALCULATE详解
    DAX 第三篇:过滤器函数
    DAX 第二篇:计算上下文
    DAX 第一篇:数据模型
    Git 第二篇:基本操作
  • 原文地址:https://www.cnblogs.com/zhangleo/p/10768022.html
Copyright © 2020-2023  润新知