zoukankan      html  css  js  c++  java
  • POJ 2987 最大权闭合图

    题意:

     一个公司打算解雇一些员工,已知解雇每个人的收益值(可能为负)。解雇某一个人后,他的下属也将被解雇,求最大收益是多少,在取得最大收益时需要解雇多少人。

    题解:

    建图不多啰嗦,挺裸的~

    求最少的割边数目,可以从源点对残量网络进行一次DFS,每个割都会将源点和汇点隔开,所以从源点DFS下去一定会碰到某个割dfs停止,这时遍历过的点数最少的裁员数目。那种直接找满流边的做法是显然不对的奥~

    ps:总是wa盛怒之下,把所有int替换了ac了。。。

    View Code
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cstdlib>
      4 #include <iostream>
      5 
      6 #define N 100100
      7 #define M 3000000
      8 #define INF 100000000
      9 
     10 using namespace std;
     11 //理解最大权闭合图的最小割的含义 
     12 __int64 head[N],to[M],next[M],len[M],sum,n,m,cnt,S,T,layer[N],q[M<<2],num,ans;
     13 bool vis[N];
     14 
     15 inline void add(__int64 u,__int64 v,__int64 wp)
     16 {
     17     to[cnt]=v; len[cnt]=wp; next[cnt]=head[u]; head[u]=cnt++;
     18     to[cnt]=u; len[cnt]=0; next[cnt]=head[v]; head[v]=cnt++;
     19 }
     20 
     21 void read()
     22 {
     23     memset(head,-1,sizeof head);cnt=0;
     24     S=0,T=n+1;sum=0;
     25     for(__int64 i=1,a;i<=n;i++)
     26     {
     27         scanf("%I64d",&a);
     28         if(a>=0)
     29         {
     30             sum+=a;
     31             add(S,i,a);
     32         }
     33         else add(i,T,-a);
     34     }
     35     for(__int64 i=1,a,b;i<=m;i++)
     36     {
     37         scanf("%I64d%I64d",&a,&b);
     38         add(a,b,INF);
     39     }
     40 }
     41 
     42 bool bfs()
     43 {
     44     memset(layer,-1,sizeof layer);
     45     __int64 h=1,t=2,sta;
     46     q[1]=S; layer[S]=0;
     47     while(h<t)
     48     {
     49         sta=q[h++];
     50         for(__int64 i=head[sta];~i;i=next[i])
     51             if(len[i]&&layer[to[i]]<0)
     52             {
     53                 layer[to[i]]=layer[sta]+1;
     54                 q[t++]=to[i];
     55             } 
     56     }
     57     return layer[T]!=-1;
     58 }
     59 
     60 __int64 find(__int64 u,__int64 cur_flow)
     61 {
     62     if(u==T) return cur_flow;
     63     __int64 result=0,tmp;
     64     for(__int64 i=head[u];~i&&result<cur_flow;i=next[i])
     65         if(len[i]&&layer[to[i]]==layer[u]+1)
     66         {
     67             tmp=find(to[i],min(cur_flow-result,len[i]));
     68             len[i]-=tmp; len[i^1]+=tmp; result+=tmp;
     69         }
     70     if(!result) layer[u]=-1;
     71     return result;
     72 }
     73 
     74 void dinic()
     75 {
     76     ans=0;
     77     while(bfs()) ans+=find(S,INF);
     78     
     79 }
     80 
     81 void dfs(__int64 u)
     82 {
     83     if(u==T) return;
     84     vis[u]=true;
     85     for(__int64 i=head[u];~i;i=next[i])
     86         if(!vis[to[i]]&&len[i]>0)
     87             dfs(to[i]);
     88 }
     89 
     90 int main()
     91 {
     92     while(scanf("%I64d%I64d",&n,&m)!=EOF)
     93     {
     94         read();
     95         dinic();
     96         num=0;
     97         memset(vis,0,sizeof vis);
     98         dfs(S);
     99         for(__int64 i=1;i<=n;i++)
    100             if(vis[i]) num++;
    101         printf("%I64d %I64d\n",num,sum-ans);
    102     }
    103     return 0;
    104 }
    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    获取设备信息
    获取Mac地址
    常用正则
    几个字段相同的纪录去重留下主键最小的一条纪录
    mysql查询数据库中包含某字段(列名)的所有表
    nginx反向代理
    Eureka参数配置项详解
    html5验证自适应
    synchronized对象解析
    多线程进行数据同步
  • 原文地址:https://www.cnblogs.com/proverbs/p/2850344.html
Copyright © 2011-2022 走看看