zoukankan      html  css  js  c++  java
  • 网络流24题-试题库问题

    试题库问题

    时空限制1000ms / 128MB

    题目描述

    «问题描述:

    假设一个试题库中有n道试题。每道试题都标明了所属类别。同一道题可能有多个类别属性。现要从题库中抽取m 道题组成试卷。并要求试卷包含指定类型的试题。试设计一个满足要求的组卷算法。

    «编程任务:

    对于给定的组卷要求,计算满足要求的组卷方案。

    输入输出格式

    输入格式:

    第1行有2个正整数k和n (2 <=k<= 20, k<=n<= 1000)

    k 表示题库中试题类型总数,n 表示题库中试题总数。第2 行有k 个正整数,第i 个正整数表示要选出的类型i的题数。这k个数相加就是要选出的总题数m。接下来的n行给出了题库中每个试题的类型信息。每行的第1 个正整数p表明该题可以属于p类,接着的p个数是该题所属的类型号。

    输出格式:

    第i 行输出 “i:”后接类型i的题号。如果有多个满足要求的方案,只要输出1个方案。如果问题无解,则输出“No Solution!”。

    输入输出样例

    输入样例: 
    3 15
    3 3 4
    2 1 2
    1 3
    1 3
    1 3
    1 3
    3 1 2 3
    2 2 3
    2 1 3
    1 2
    1 2
    2 1 2
    2 1 3
    2 1 2
    1 1
    3 1 2 3
    输出样例: 
    1: 1 6 8
    2: 7 9 10
    3: 2 3 4 5

     


    最大流。

    虽然点数很多,但是每条边的流量很小,这样增广次数也不会很多,用dinic可以过。(而且dinic也很难达到上界复杂度,通常一千左右的点,就算是完全图,如果边权很小的话,dinic也跑的飞快)。

    #include<bits/stdc++.h>
    #define N 1035
    using namespace std;
    
    typedef struct
    {
        int v;
        long long flow;
    } ss;
    ss edg[N*N];
    vector<int>edges[N];
    int now_edges=0;
    
    void addedge(int u,int v,long long flow)
    {
        edges[u].push_back(now_edges);
        edg[now_edges++]=(ss)
        {
            v,flow
        };
        edges[v].push_back(now_edges);
        edg[now_edges++]=(ss)
        {
            u,0
        };
    }
    
    int S,T,current[N];
    int dis[N]= {0};
    int bfs()
    {
        memset(dis,0,sizeof(dis));
        dis[S]=0;
        queue<int>q;
        q.push(S);
    
        while(!q.empty())
        {
            int now=q.front();
            q.pop();
    
            int Size=edges[now].size();
            for(int i=0; i<Size; i++)
            {
                ss e=edg[edges[now][i]];
                if(e.flow>0&&dis[e.v]==0)
                {
                    dis[e.v]=dis[now]+1;
                    q.push(e.v);
                }
            }
        }
        return dis[T];
    }
    
    
    long long dfs(int now,long long maxflow)
    {
        if(now==T)return maxflow;
        int Size=edges[now].size();
        for(int i=current[now]; i<Size; i++)
        {
            current[now]=i;
            ss &e=edg[edges[now][i]];
            if(e.flow>0&&dis[e.v]==dis[now]+1)
            {
                long long flow=dfs(e.v,min(e.flow,maxflow));
                if(flow!=0)
                {
                    e.flow-=flow;
                    edg[edges[now][i]^1].flow+=flow;
                    return flow;
                }
            }
        }
        return 0;
    }
    
    long long dinic()
    {
        long long ans=0,flow;
        while(bfs())
        {
            memset(current,0,sizeof(current));
            while(flow=dfs(S,LLONG_MAX/2))ans+=flow;
        }
        return ans;
    }
    
    
    int main()
    {
        int k,n;
        long long tot=0;
        scanf("%d %d",&k,&n);
        S=n+k+1;
        T=S+1;
    
        for(int i=1; i<=k; i++)
        {
            int a;
            scanf("%d",&a);
            tot+=a;
            addedge(n+i,T,a);
        }
    
        for(int i=1; i<=n; i++)
        {
            int a,p;
            scanf("%d",&p);
            while(p--)
            {
                scanf("%d",&a);
                addedge(i,n+a,1);
            }
    
            addedge(S,i,1);
        }
    
        long long ans=dinic();
        if(ans==tot)
        {
            for(int i=1; i<=k; i++)
            {
                printf("%d:",i);
    
                int Size=edges[n+i].size();
                for(int j=0; j<Size; j++)
                    if(edg[edges[n+i][j]].flow>0)printf(" %d",edg[edges[n+i][j]].v);
                printf("
    ");
            }
        }
        else
            printf("No Solution!
    ");
    
        return 0;
    }
    View Code
  • 相关阅读:
    Java学习第十五章 之 Map、可变参数、Collections
    Java第十四章 之 List、Set
    Java学习第十三章 之 常用API
    通过shell终端上传下载文件
    javamail邮件发送
    linux防火墙添加例外端口shell脚本
    MySQL批量更新
    MySQL返回列名
    发现一个有意思的东西
    struts2,action方法自动执行两次
  • 原文地址:https://www.cnblogs.com/tian-luo/p/9552027.html
Copyright © 2011-2022 走看看