zoukankan      html  css  js  c++  java
  • 试题库问题

    嘟嘟嘟

    做了几道网络流的题后,就感觉这道题还是挺简单的了……

    这是一个二分图多重匹配问题,关键还是在建图:图的右侧是k个节点,代表每一个类型的试卷,然后都连一条容量为该类型题数通往汇点的边。图的左侧是每一个试题,因为每一个试题只能用一次,所以和源点连一条容量为1的边。然后如果试题 i 属于第 j 类试题,就在 (i, j + n)之间连一条边(j + n是为了防止编号重复,边全只要大于0就行,因为从源点出发,每一道题都限制了只能用一次)。

    然后跑最大流就行了,只要判断最大流是否等于m就行。

    输出方案就是对于 i : 1~k,遍历他的所有出边,如果指向 j  (1 <= j <= n),且这条边流了-1,就说明 j 试题被选进了第 i 类试题中。为什么是流了-1呢?因为这条边是反向的,从(j, i)流了1,那么(i, j)就流了-1.

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<algorithm>
      5 #include<cstring>
      6 #include<cstdlib>
      7 #include<cctype>
      8 #include<vector>
      9 #include<stack>
     10 #include<queue>
     11 using namespace std;
     12 #define enter puts("") 
     13 #define space putchar(' ')
     14 #define Mem(a) memset(a, 0, sizeof(a))
     15 typedef long long ll;
     16 typedef double db;
     17 const int INF = 0x3f3f3f3f;
     18 const db eps = 1e-8;
     19 const int maxn = 1025;
     20 inline ll read()
     21 {
     22     ll ans = 0;
     23     char ch = getchar(), last = ' ';
     24     while(!isdigit(ch)) {last = ch; ch = getchar();}
     25     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     26     if(last == '-') ans = -ans;
     27     return ans;
     28 }
     29 inline void write(ll x)
     30 {
     31     if(x < 0) x = -x, putchar('-');
     32     if(x >= 10) write(x / 10);
     33     putchar(x % 10 + '0');
     34 }
     35 
     36 int k, n, t, sum = 0;
     37 
     38 struct Edge
     39 {
     40     int from, to, cap, flow;
     41 };
     42 vector<Edge> edges;
     43 vector<int> G[maxn << 1];
     44 void addEdge(int from, int to, int w)
     45 {
     46     edges.push_back((Edge){from, to, w, 0});
     47     edges.push_back((Edge){to, from, 0, 0});
     48     int sz = edges.size();
     49     G[from].push_back(sz - 2);
     50     G[to].push_back(sz - 1);
     51 }
     52 
     53 int dis[maxn << 1];
     54 bool bfs()
     55 {
     56     Mem(dis); dis[0] = 1;
     57     queue<int> q; q.push(0);
     58     while(!q.empty())
     59     {
     60         int now = q.front(); q.pop();
     61         for(int i = 0; i < (int)G[now].size(); ++i)
     62         {
     63             Edge& e = edges[G[now][i]];
     64             if(!dis[e.to] && e.cap > e.flow)
     65             {
     66                 dis[e.to] = dis[now] + 1;
     67                 q.push(e.to);
     68             }
     69         }
     70     }
     71     return dis[t];
     72 }
     73 int cur[maxn << 1];
     74 int dfs(int now, int res)
     75 {
     76     if(now == t || res == 0) return res;
     77     int flow = 0, f;
     78     for(int& i = cur[now]; i < (int)G[now].size(); ++i)
     79     {
     80         Edge& e = edges[G[now][i]];
     81         if(dis[e.to] == dis[now] + 1 && (f = dfs(e.to, min(res, e.cap - e.flow))) > 0)
     82         {
     83             e.flow += f;
     84             edges[G[now][i] ^ 1].flow -= f;
     85             flow += f;
     86             res -= f;
     87             if(res == 0) break;
     88         }
     89     }
     90     return flow;
     91 }
     92 
     93 int maxflow()
     94 {
     95     int flow = 0;
     96     while(bfs())
     97     {
     98         Mem(cur);
     99         flow += dfs(0, INF);
    100     }
    101     return flow;
    102 }
    103 
    104 int main()
    105 {
    106     k = read(); n = read();
    107     t = k + n + 1;
    108     for(int i = 1; i <= k; ++i) {int x = read(); sum += x; addEdge(n + i, t, x);}
    109     for(int i = 1; i <= n; ++i)
    110     {
    111         int p = read();
    112         addEdge(0, i, 1);
    113         for(int j = 1; j <= p; ++j) addEdge(i, n + read(), 1);
    114     }
    115     if(maxflow() != sum) printf("No Solution!
    ");
    116     else
    117     {
    118         for(int i = 1; i <= k; ++i)
    119         {
    120             write(i); putchar(':'); space;
    121             for(int j = 0; j < (int)G[i + n].size(); ++j)
    122             {
    123                 Edge e = edges[G[i + n][j]];
    124                 if(e.to <= n && e.flow == -1) write(e.to), space;
    125             }
    126             enter;
    127         }
    128     }
    129     return 0;
    130 }
    View Code
  • 相关阅读:
    vue.js引用出错-script代码块放在head和body中的区别
    Notes:一致性哈希算法
    TCP为什么不是两次握手而是三次?
    windows上SSH服务连接远程主机失败
    Centos安装vsftp服务
    使用JavaMail实现发送邮件功能
    在进行javaIO写文件操作后文件内容为空的情况
    Struts2---动态方法调用
    golang的吐槽
    select函数源码阅读
  • 原文地址:https://www.cnblogs.com/mrclr/p/9588000.html
Copyright © 2011-2022 走看看