zoukankan      html  css  js  c++  java
  • BZOJ-1497 [NOI2006]最大获利 最小割

    题面

    题意:有n个地点可以选择是否修建,建的成本为p[i],用户有M个,对于每个用户,如果地点Ai和Bi都修了的,那么你就可以获得Ci的收益,现在问你最多能获得多少钱

    题解:考虑最小割

       对于每个地点 build(s,i,p[i])
         对于每个用户 build(i+n,t,c[i])
           他所需要的2个地点,build(a[i],i+n,inf);build(b[i],i+n,inf)
           然后用总的收益减去最小割就是答案 Why?
           我们想割掉的是连向s的边 表示我们修了这个地点 成本增加了
           割掉的是连向t的边 表示我们没有赚到这个客户的钱 获利减少了

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 55005
     4 #define M 160000
     5 const int inf=0x7fffffff/3;
     6 namespace Dinic
     7 {
     8     int head[N],head2[N],p=1;
     9     struct Rec
    10     {
    11         int go,nex,c;
    12     }eg[M*2];
    13     void build(int a,int b,int c)
    14     {
    15         eg[++p]=(Rec){b,head[a],-c};
    16         head[a]=p;
    17         eg[++p]=(Rec){a,head[b],0};
    18         head[b]=p;
    19     }
    20     int dis[N],Q[N],s[N],S,T,stop,ans;
    21     bool bfs()
    22     {
    23         memset(dis,0,sizeof(dis));
    24         dis[T]=1;
    25         Q[1]=T;
    26         for (int p1=1,p2=1;p1<=p2;p1++)
    27         {
    28             for (int i=head[Q[p1]];i;i=eg[i].nex)
    29                 if (eg[i^1].c<0&&!dis[eg[i].go])
    30                 {
    31                     dis[eg[i].go]=dis[Q[p1]]+1;
    32                     Q[++p2]=eg[i].go;
    33                 }
    34         }
    35         if (!dis[S]) return false;
    36         memcpy(head2,head,sizeof(head));
    37         return true;
    38     }
    39     bool dinic(int p,int top)
    40     {
    41         if (p==T)
    42         {
    43             int x=inf;
    44             for (int i=1;i<=top-1;i++) if (-eg[s[i]].c<x) x=-eg[s[i]].c,stop=i;
    45             for (int i=1;i<=top-1;i++) eg[s[i]].c+=x,eg[s[i]^1].c-=x;
    46             ans+=x;
    47             return true;
    48         }
    49         for (int &i=head2[p];i;i=eg[i].nex)
    50         {
    51             if (eg[i].c<0&&dis[eg[i].go]==dis[p]-1)
    52             {
    53                 s[top]=i;
    54                 if (dinic(eg[i].go,top+1)&&top!=stop) return true;
    55             }
    56         }
    57         return false;
    58     }
    59     int ask()
    60     {
    61         ans=0;
    62         while (bfs()) dinic(S,1);
    63         return ans; 
    64     }
    65     void init(int _S,int _T){
    66         S=_S,T=_T;
    67     }
    68 }
    69 using namespace Dinic;
    70 void clear()
    71 {
    72     p=1;
    73     memset(head,0,sizeof(head));
    74 }
    75 int n,m,ss,tt,x,y,z,why;
    76 int main()
    77 {
    78     scanf("%d%d",&n,&m);
    79     ss=0;tt=n+m+1;
    80     init(ss,tt);
    81     for (int i=1;i<=n;i++)
    82     {
    83         scanf("%d",&x);
    84         build(ss,i,x);
    85     }
    86     for (int i=1;i<=m;i++)
    87     {
    88         scanf("%d%d%d",&x,&y,&z);
    89         why+=z;
    90         build(i+n,tt,z);
    91         build(y,i+n,inf);
    92         build(x,i+n,inf);
    93     }
    94     printf("%d
    ",why-ask());
    95     return 0;
    96 }
    Anderyi!
  • 相关阅读:
    【LeetCode OJ】Remove Element
    【LeetCode OJ】Remove Duplicates from Sorted Array
    【LeetCode OJ】Swap Nodes in Pairs
    【LeetCode OJ】Merge Two Sorted Lists
    【LeetCode OJ】Remove Nth Node From End of List
    【LeetCode OJ】Two Sum
    【LeetCode OJ】Majority Element
    最长公共子序列问题
    php fopen与file_get_contents的区别
    PHP 技巧集合
  • 原文地址:https://www.cnblogs.com/qywhy/p/9717751.html
Copyright © 2011-2022 走看看