• 圆桌问题 【网络流24题】


     

    思路

      题目已经给出了暗示

      即题目中给出了一个二分图

      显然,可以把人和桌子作为二分图的两个阵营

      由于题目中给出的限制:每个单位的人都必须坐在不同的桌子上

      所以把单位向每个桌子连一条流量为1的边

      由S向单位连单位人数的边 

      由桌子向T连桌子容量的边  

      然后跑一次最大流,最后枚举每个单位的邻接边,通过判断残量网络上的值可以求出这个人去了哪张桌子

      朴素的Dinic会T最后一个点

      考虑当前弧优化来优化朴素Dinic算法,只需要70ms即可跑完

    CODE

      1 #include <bits/stdc++.h>
      2 #define dbg(x) cout << #x << "=" << x << endl
      3 #define eps 1e-8
      4 #define pi acos(-1.0)
      5 
      6 using namespace std;
      7 typedef long long LL;
      8 
      9 const int inf = 0x3f3f3f3f;
     10 
     11 template<class T>inline void read(T &res)
     12 {
     13     char c;T flag=1;
     14     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;res=c-'0';
     15     while((c=getchar())>='0'&&c<='9')res=res*10+c-'0';res*=flag;
     16 }
     17 
     18 namespace _buff {
     19     const size_t BUFF = 1 << 19;
     20     char ibuf[BUFF], *ib = ibuf, *ie = ibuf;
     21     char getc() {
     22         if (ib == ie) {
     23             ib = ibuf;
     24             ie = ibuf + fread(ibuf, 1, BUFF, stdin);
     25         }
     26         return ib == ie ? -1 : *ib++;
     27     }
     28 }
     29 
     30 int qread() {
     31     using namespace _buff;
     32     int ret = 0;
     33     bool pos = true;
     34     char c = getc();
     35     for (; (c < '0' || c > '9') && c != '-'; c = getc()) {
     36         assert(~c);
     37     }
     38     if (c == '-') {
     39         pos = false;
     40         c = getc();
     41     }
     42     for (; c >= '0' && c <= '9'; c = getc()) {
     43         ret = (ret << 3) + (ret << 1) + (c ^ 48);
     44     }
     45     return pos ? ret : -ret;
     46 }
     47 
     48 const int maxn = 5e4 + 7;
     49 
     50 int s, t, cnt = 1;
     51 int head[maxn << 1], edge[maxn << 1], nxt[maxn << 1], vis[maxn << 1];
     52 int w[maxn << 1];//残量网络
     53 int rev[maxn << 1];
     54 int depth[maxn << 1];//图层
     55 int n, m;
     56 int cur[maxn << 1];//当前弧优化
     57 
     58 void BuildGraph(int u, int v, int cap) {
     59     ++cnt;
     60     edge[cnt] = v;
     61     nxt[cnt] = head[u];
     62     rev[cnt] = cnt + 1;
     63     w[cnt] = cap;
     64     head[u] = cnt;
     65 
     66     ++cnt;
     67     edge[cnt] = u;
     68     nxt[cnt] = head[v];
     69     w[cnt] = 0;
     70     rev[cnt] = cnt - 1;
     71     head[v] = cnt;
     72 }
     73 
     74 bool bfs(int x) {
     75     queue<int> q;
     76     for ( int i = 0; i <= t; ++i ) {
     77         cur[i] = head[i];
     78     }
     79     while(!q.empty()) {
     80         q.pop();
     81     }
     82     memset(depth, 63, sizeof(depth));
     83     depth[s] = 0;
     84     q.push(s);
     85     do {
     86         int u = q.front();
     87         q.pop();
     88         for ( int i = head[u]; i; i = nxt[i] ) {
     89             int v = edge[i];
     90             if(w[i] > 0 && depth[u] + 1 < depth[v]) {
     91                 depth[v] = depth[u] + 1;
     92                 q.push(v);
     93                 if(v == t) {
     94                     return true;
     95                 }
     96             }
     97         }
     98     } while (!q.empty());
     99     if(depth[t] < inf)
    100         return true;
    101     return false;
    102 }
    103 
    104 int dfs(int u, int dist) {
    105     if(!dist || u == t) {
    106         return dist;
    107     }
    108     int flow = 0, f;
    109     for ( int i = cur[u]; i; i = nxt[i] ) {
    110         cur[u] = 1;
    111         int v = edge[i];
    112         if(depth[v] == depth[u] + 1 && (f = dfs(v, min(dist, w[i])))) {
    113             flow += f;
    114             dist -= f;
    115             w[i] -= f;
    116             w[i ^ 1] += f;
    117             if(!dist)
    118                 break;
    119         }
    120     }
    121     return flow;
    122 }
    123 
    124 int pp[maxn];
    125 int table[maxn];
    126 int sum = 0;
    127 
    128 int main()
    129 {
    130     //freopen("data.txt", "r", stdin);
    131     read(m); read(n);
    132     for ( int i = 1; i <= m; ++i ) {
    133         read(pp[i]);
    134         sum += pp[i];
    135     }
    136     for ( int i = 1; i <= n; ++i ) {
    137         read(table[i]);
    138     }
    139     s = 0, t = n + m + 1;
    140     for ( int i = 1; i <= m; ++i ) {
    141         BuildGraph(s, i, pp[i]);
    142         for ( int j = 1; j <= n; ++j ) {
    143             BuildGraph(i, j + m, 1);
    144         }
    145     }
    146     for ( int i = 1; i <= n; ++i ) {
    147         //printf("table[%d]:%d
    ",i, table[i]);
    148         BuildGraph(i + m, t, table[i]);
    149     }   
    150     //dbg(sum);
    151     int ans = 0;
    152     while(bfs(s)) {
    153         ans += dfs(0, 0x7f7f7f7f);
    154     }
    155     //dbg(ans);
    156     if(sum != ans) {
    157         puts("0");
    158     }
    159     else {
    160         cout << 1 << endl;
    161         for ( int i = 1; i <= m; ++i ) {
    162             for ( int j = head[i]; j; j = nxt[j] ) {
    163                 int to = edge[j];
    164                 if(to != t && !w[j]) {
    165                     printf("%d ",to - m);
    166                     //printf("cap[%d]:%d
    ",j, w[j]);
    167                 }
    168             }
    169             puts("");
    170         }
    171     }
    172     return 0;
    173 }
    View Code
  • 相关阅读:
    R语言nest_join()函数
    R语言行/列合并
    ffmpeg 命令将视频转化为图帧
    Natas Wargame Level20 Writeup(会话状态注入/篡改)
    vim简明教程--半小时从入门到精通
    笔记:Spring Cloud Hystrix 异常处理、缓存和请求合并
    【Ecstore2.0】导出问题解决(未导出或导出文件为0字节)
    Android Handler消息处理顺序分析
    着色器语言之变量类型
    Redis源码分析(十一)--- memtest内存检测
  • 原文地址:https://www.cnblogs.com/orangeko/p/12827825.html
Copyright © 2020-2023  润新知