• CF311E Biologist


    嘟嘟嘟

     

    很显然是一道最小割模型。

    做完几道题后。图的大概就能想出来了:

    1.对于每一个动物,如果是0,就和s连一条边,否则向t连一条边。

    2.对于每一个任务,题中要求最大利润,可以转化成最小损失。

      (1)如果都要变成1,就向汇点连一条w +g(如果有的话)的边;否则从源点连一条w +g的边。接下来

      (2)对于任务中涉及的每一个点,刚开始我想如果任务要变成1,而他本身还是1就不连边,否则连一条INF的边,然后我就发现任务之间是互相影响的,而这种方式体现不出来,然后我就想不出来了……

         题解是这么说的:如果这个任务是0,就向所有涉及到的点连边,否则这些点向他连边,然后我就画了一个图,发现好像还真是这么回事:

     

    如果我们要达成任务1的话,就要割掉(2->t), (3->t)两条边,但是图还是联通的,因此还得割掉([2]->t)的边,也就同时说明了任务2不可达成。

      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, x) memset(a, x, sizeof(a))
     15 #define rg register
     16 typedef long long ll;
     17 typedef double db;
     18 const int INF = 0x3f3f3f3f;
     19 const db eps = 1e-8;
     20 const int maxn = 1.2e4 + 5;
     21 inline ll read()
     22 {
     23     ll ans = 0;
     24     char ch = getchar(), last = ' ';
     25     while(!isdigit(ch)) {last = ch; ch = getchar();}
     26     while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
     27     if(last == '-') ans = -ans;
     28     return ans;
     29 }
     30 inline void write(ll x)
     31 {
     32     if(x < 0) x = -x, putchar('-');
     33     if(x >= 10) write(x / 10);
     34     putchar(x % 10 + '0');
     35 }
     36 
     37 int n, m, t;
     38 int g, val[maxn], sum = 0;
     39 bool a[maxn];
     40 
     41 struct Edge
     42 {
     43     int from, to, cap, flow;
     44 };
     45 vector<Edge> edges;
     46 vector<int> G[maxn];
     47 void addEdge(int from, int to, int w)
     48 {
     49     edges.push_back((Edge){from, to, w, 0});
     50     edges.push_back((Edge){to, from, 0, 0});
     51     int sz = edges.size();
     52     G[from].push_back(sz - 2);
     53     G[to].push_back(sz - 1);
     54 }
     55 
     56 int dis[maxn];
     57 bool bfs()
     58 {
     59     Mem(dis, 0); dis[0] = 1;
     60     queue<int> q; q.push(0);
     61     while(!q.empty())
     62     {
     63         int now = q.front(); q.pop();
     64         for(int i = 0; i < (int)G[now].size(); ++i)
     65         {
     66             Edge& e = edges[G[now][i]];
     67             if(!dis[e.to] && e.cap > e.flow)
     68             {
     69                 dis[e.to] = dis[now] + 1;
     70                 q.push(e.to);    
     71             }
     72         }
     73     }
     74     return dis[t];
     75 }
     76 int cur[maxn];
     77 int dfs(int now, int res)
     78 {
     79     if(now == t || res == 0) return res;
     80     int flow = 0, f;
     81     for(int& i = cur[now]; i < (int)G[now].size(); ++i)
     82     {
     83         Edge& e = edges[G[now][i]];
     84         if(dis[e.to] == dis[now] + 1 && (f = dfs(e.to, min(res, e.cap - e.flow))) > 0)
     85         {
     86             e.flow += f;
     87             edges[G[now][i] ^ 1].flow -= f;
     88             flow += f; res -= f;
     89             if(res == 0) break;
     90         }
     91     }
     92     return flow;
     93 }
     94 
     95 int minCut()
     96 {
     97     int flow = 0;
     98     while(bfs())
     99     {
    100         Mem(cur, 0);
    101         flow += dfs(0, INF);
    102     }
    103     return flow;
    104 }
    105 
    106 int main()
    107 {
    108     n = read(), m = read(), g = read();
    109     t = n + m + 1;
    110     for(int i = 1; i <= n; ++i) a[i] = (bool)read();
    111     for(int i = 1; i <= n; ++i)
    112     {
    113         int x = read();
    114         if(a[i]) addEdge(i, t, x);
    115         else addEdge(0, i, x);
    116     }
    117     for(int i = 1; i <= m; ++i)
    118     {
    119         int op = read(), w = read(), k = read();
    120         sum += w;
    121         for(int j = 1; j <= k; ++j)
    122         {
    123             int id = read();
    124             if(op) addEdge(id, i + n, INF);
    125             else addEdge(i + n, id, INF);
    126         }
    127         int flg = read();
    128         if(op) addEdge(i + n, t, w + flg * g);
    129         else addEdge(0, i + n, w + flg * g);
    130     }
    131     write(sum - minCut()); enter;
    132     return 0;
    133 }
    View Code
  • 相关阅读:
    淘宝轮播图带前后按钮
    仿淘宝轮播图 ,需要运动框架
    运动框架
    js 淡入淡出的图片
    js 分享到按钮
    js动态改变时间
    js事件委托,可以使新添加的元素具有事件(event运用)
    div高度自适应(父元素未知,所有高度跟随子元素最大的高度)
    CSS子元素居中(父元素宽高已知,子元素未知)
    css仅在指定ie浏览器生效
  • 原文地址:https://www.cnblogs.com/mrclr/p/9699220.html
Copyright © 2020-2023  润新知