zoukankan      html  css  js  c++  java
  • [HihoCoder1398]网络流五·最大权闭合子图

    题目大意:
    有$N$项活动$M$个人,每个活动$act_i$有一个正的权值$a_i$,每个人$stu_i$有一个负的权值$b_i$。
    每项活动能够被完成当且仅当该项活动所需的所有人到场。
    如何选择活动使最终权值总和最大?
    即对于给定的有向无环图,求出最大权闭合子图的权值。

    结论:
    最大权闭合子图的权值等于所有正权点之和减去最小割。

    思路:
    引理:
    1.最小割一定是简单割;
    2.简单割一定和一个闭合子图对应。
    即最小割一定对应一个闭合子图,且就是最大权闭合子图。
    证明(摘自HihoCoder):
    首先有割的容量C(S,T)=T中所有正权点的权值之和+S中所有负权点的权值绝对值之和。
    闭合子图的权值W=S中所有正权点的权值之和-S中所有负权点的权值绝对值之和。
    则有C(S,T)+W=T中所有正权点的权值之和+S中所有正权点的权值之和=所有正权点的权值之和。
    所以W=所有正权点的权值之和-C(S,T)。

     1 #include<queue>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<vector>
     5 #include<cstring>
     6 inline int getint() {
     7     char ch;
     8     while(!isdigit(ch=getchar()));
     9     int x=ch^'0';
    10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    11     return x;
    12 }
    13 const int inf=0x7fffffff;
    14 int s,t;
    15 const int E=80800,V=402;
    16 struct Edge {
    17     int from,to,remain;
    18 };
    19 Edge e[E];
    20 std::vector<int> g[V];
    21 int sz=0;
    22 inline void add_edge(const int u,const int v,const int w) {
    23     e[sz]=(Edge){u,v,w};
    24     g[u].push_back(sz);
    25     sz++;
    26 }
    27 int p[V],a[V];
    28 inline int Augment() {
    29     memset(a,0,sizeof a);
    30     a[s]=inf;
    31     std::queue<int> q;
    32     q.push(s);
    33     while(!q.empty()&&!a[t]) {
    34         int x=q.front();
    35         q.pop();
    36         for(unsigned i=0;i<g[x].size();i++) {
    37             Edge &y=e[g[x][i]];
    38             if(!a[y.to]&&y.remain) {
    39                 p[y.to]=g[x][i];
    40                 a[y.to]=std::min(a[x],y.remain);
    41                 q.push(y.to);
    42             }
    43         }
    44     }
    45     return a[t];
    46 }
    47 inline int EdmondsKarp() {
    48     int maxflow=0;
    49     while(int flow=Augment()) {
    50         for(int i=t;i!=s;i=e[p[i]].from) {
    51             e[p[i]].remain-=flow;
    52             e[p[i]^1].remain+=flow;
    53         }
    54         maxflow+=flow;
    55     }
    56     return maxflow;
    57 }
    58 int main() {
    59     int n=getint(),m=getint();
    60     s=0,t=n+m+1;
    61     for(int i=1;i<=m;i++) {
    62         add_edge(n+i,t,getint());
    63         add_edge(t,n+i,0);
    64     }
    65     int sum=0;
    66     for(int i=1;i<=n;i++) {
    67         int a=getint();
    68         sum+=a;
    69         add_edge(s,i,a);
    70         add_edge(i,s,0);
    71         for(int k=getint();k;k--) {
    72             int v=getint();
    73             add_edge(i,n+v,inf);
    74             add_edge(n+v,i,0);
    75         }
    76     }
    77     printf("%d
    ",sum-EdmondsKarp());
    78     return 0;
    79 }



  • 相关阅读:
    php实现题目抢答、商品秒杀等类型的需求
    php实现批量修改文件名称
    php微信支付问题之 cURL error 60: SSL certificate: unable to get local issuer certificate
    laravel5.2之logout注销账号无效
    分布式版本控制git常见问题之gitignore冲突(精简版)
    laravel实现多数据库连接配置
    laravel实现excel表格导出
    js实现超出一定字数隐藏并用省略号"..."代替,点击后又可进行展开和收起,
    你会python不?当你听到这个问题要谨慎回答!!!
    DirectX 入门1-初识DirectX Tool Kit
  • 原文地址:https://www.cnblogs.com/skylee03/p/7252279.html
Copyright © 2011-2022 走看看