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

    题目大意:

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


    思路:

    这道题很明显是一个二分图。所以首选Dinic
    对于每一个试卷,将它连向汇点T,流量为所需的题目总数;而每一道题就连向原点S,流量为1。而中间则将每一道题连向它可以放入的试卷,流量为1。之后跑一边Dinic,若sum=num则可以组成试卷,否则不行。


    代码:

    #include <cstdio>
    #include <queue>
    #include <iostream>
    #include <cstring>
    #define Inf 0x7f
    #define INF 2147483647
    using namespace std;
    
    int n,m,k,s,t,head[3000001],dep[3000001],num,x,y,sum,ans;
    
    struct edge
    {
        int to,next,c;
    }e[3000001];
    
    void add(int from,int to,int c)
    {
        k++;
        e[k].c=c;
        e[k].to=to;
        e[k].next=head[from];
        head[from]=k;
    }
    
    bool bfs()  //分层不解释
    {
        memset(dep,Inf,sizeof(dep));    
        dep[s]=0;
        queue<int> q;
        q.push(s);
        while (q.size())
        {
            int u=q.front();
            q.pop();
            for (int i=head[u];i;i=e[i].next)
            {
                int v=e[i].to;
                if (dep[u]+1<dep[v]&&e[i].c)
                {
                    dep[v]=dep[u]+1;
                    q.push(v);
                }
            }
        }
        return (dep[t]<Inf);
    }
    
    int dfs(int u,int low)
    {
        int lows=0;
        if (u==t) return low;  //到达汇点
        for (int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if (dep[v]==dep[u]+1&&e[i].c)
            {
                lows=dfs(v,min(e[i].c,low));  //求最小边权
                if (!lows) continue;  //最小边权为0
                e[i].c-=lows;  //正向边
                e[((i+1)^1)-1].c+=lows;  //反向边
                return lows;
            }
        }
        return 0;
    }
    
    bool print()  //输出不解释
    {
        for (int i=n+1;i<=n+m;i++)
        {
            printf("%d:",i-n);
            for (int j=head[i];j;j=e[j].next)
            {
                int v=e[j].to;
                if (v<t&&e[j].c)
                 printf(" %d",v);
            }
            putchar(10); 
        }
        return false;
    }
    
    int main()
    {
        scanf("%d%d",&m,&n);
        s=0;
        t=n+m+1;
        for (int i=1;i<=m;i++)
        {
            scanf("%d",&x);
            num+=x;
            add(n+i,t,x);
            add(t,n+i,0);
        }
        for (int j=1;j<=n;j++)
        {
            add(s,j,1);
            add(j,s,0);
            scanf("%d",&x);
            for (int i=1;i<=x;i++)
            {
                scanf("%d",&y);
                add(j,n+y,1);
                add(n+y,j,0);
            }
        }
        while (bfs())  //只要能分层就循环
        {
            while (sum=dfs(s,INF))
             ans+=sum;
        }
        if (ans<num) return printf("No Solution!\n")&0;
        return print();
    }
  • 相关阅读:
    【校招面试 之 C/C++】第23题 C++ STL(五)之Set
    Cannot create an instance of OLE DB provider “OraOLEDB.Oracle” for linked server "xxxxxxx".
    Redhat Linux安装JDK 1.7
    ORA-10635: Invalid segment or tablespace type
    Symantec Backup Exec 2012 Agent for Linux 卸载
    Symantec Backup Exec 2012 Agent For Linux安装
    You must use the Role Management Tool to install or configure Microsoft .NET Framework 3.5 SP1
    YourSQLDba介绍
    PL/SQL重新编译包无反应
    MS SQL 监控数据/日志文件增长
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998812.html
Copyright © 2011-2022 走看看