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

    Language:
    Firing
    Time Limit: 5000MS   Memory Limit: 131072K
    Total Submissions: 8744   Accepted: 2631

    Description

    You’ve finally got mad at “the world’s most stupid” employees of yours and decided to do some firings. You’re now simply too mad to give response to questions like “Don’t you think it is an even more stupid decision to have signed them?”, yet calm enough to consider the potential profit and loss from firing a good portion of them. While getting rid of an employee will save your wage and bonus expenditure on him, termination of a contract before expiration costs you funds for compensation. If you fire an employee, you also fire all his underlings and the underlings of his underlings and those underlings’ underlings’ underlings… An employee may serve in several departments and his (direct or indirect) underlings in one department may be his boss in another department. Is your firing plan ready now?

    Input

    The input starts with two integers n (0 < n ≤ 5000) and m (0 ≤ m ≤ 60000) on the same line. Next follows n + m lines. The first n lines of these give the net profit/loss from firing the i-th employee individuallybi (|bi| ≤ 107, 1 ≤ i ≤ n). The remaining m lines each contain two integers i and j (1 ≤ ij ≤ n) meaning the i-th employee has the j-th employee as his direct underling.

    Output

    Output two integers separated by a single space: the minimum number of employees to fire to achieve the maximum profit, and the maximum profit.

    Sample Input

    5 5
    8
    -9
    -20
    12
    -10
    1 2
    2 5
    1 4
    3 4
    4 5

    Sample Output

    2 2

    Hint

    As of the situation described by the sample input, firing employees 4 and 5 will produce a net profit of 2, which is maximum.
     
    很基础的最大权闭合图
     
      1 #include<iostream>
      2 #include<queue>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<climits>
      6 #define MAXE 65100*2
      7 #define MAXP 5100
      8 #define Max(a,b) a>b?a:b
      9 #define Min(a,b) a<b?a:b
     10 using namespace std;
     11 struct Edge
     12 {
     13     long long int s,t,next;
     14     long long f;
     15 } edge[MAXE];
     16 long long int head[MAXP];
     17 long long int cur[MAXP];
     18 long long int pre[MAXP];
     19 long long int stack[MAXE];
     20 long long int dep[MAXP];
     21 long long int ent;
     22 long long int n,m,s,t,cot;
     23 void add(long long int start,long long int last,long long int f)
     24 {
     25     edge[ent].s=start;
     26     edge[ent].t=last;
     27     edge[ent].f=f;
     28     edge[ent].next=head[start];
     29     head[start]=ent++;
     30     edge[ent].s=last;
     31     edge[ent].t=start;
     32     edge[ent].f=0;
     33     edge[ent].next=head[last];
     34     head[last]=ent++;
     35 }
     36 bool bfs(long long int S,long long int T)
     37 {
     38     memset(pre,-1,sizeof(pre));
     39     pre[S]=0;
     40     queue<long long int>q;
     41     q.push(S);
     42     while(!q.empty())
     43     {
     44         long long int temp=q.front();
     45         q.pop();
     46         for(long long int i=head[temp]; i!=-1; i=edge[i].next)
     47         {
     48             long long int temp2=edge[i].t;
     49             if(pre[temp2]==-1&&edge[i].f)
     50             {
     51                 pre[temp2]=pre[temp]+1;
     52                 q.push(temp2);
     53             }
     54         }
     55     }
     56     return pre[T]!=-1;
     57 }
     58 long long int dinic(long long int start,long long int last)
     59 {
     60     long long int flow=0,now;
     61     while(bfs(start,last))
     62     {
     63         long long int top=0;
     64         memcpy(cur,head,sizeof(head));
     65         long long int u=start;
     66         while(1)
     67         {
     68             if(u==last)//如果找到终点结束对中间路径进行处理并计算出该流
     69             {
     70                 long long int minn=INT_MAX;
     71                 for(long long int i=0; i<top; i++)
     72                 {
     73                     if(minn>edge[stack[i]].f)
     74                     {
     75                         minn=edge[stack[i]].f;
     76                         now=i;
     77                     }
     78                 }
     79                 flow+=minn;
     80                 for(long long int i=0; i<top; i++)
     81                 {
     82                     edge[stack[i]].f-=minn;
     83                     edge[stack[i]^1].f+=minn;
     84                 }
     85                 top=now;
     86                 u=edge[stack[top]].s;
     87             }
     88             for(long long int i=cur[u]; i!=-1; cur[u]=i=edge[i].next) //找出从u点出发能到的边
     89                 if(edge[i].f&&pre[edge[i].t]==pre[u]+1)
     90                     break;
     91             if(cur[u]==-1)//如果从该点未找到可行边,将该点标记并回溯
     92             {
     93                 if(top==0)break;
     94                 pre[u]=-1;
     95                 u=edge[stack[--top]].s;
     96             }
     97             else//如果找到了继续运行
     98             {
     99                 stack[top++]=cur[u];
    100                 u=edge[cur[u]].t;
    101             }
    102         }
    103     }
    104     return flow;
    105 }
    106 void dfs(long long int u)
    107 {
    108     cot++;
    109     dep[u]=1;
    110     for(long long int i=head[u];i!=-1;i=edge[i].next)
    111     {
    112         long long int v=edge[i].t;
    113         if(!dep[v]&&edge[i].f>0)
    114         {
    115             dfs(v);
    116         }
    117     }
    118 }
    119 int main()
    120 {
    121     while(~scanf("%lld%lld",&n,&m))
    122     {
    123         s=0;
    124         t=n+1;
    125         ent=0;
    126         long long int cost,u,v;
    127         long long int ans=0;
    128         memset(head,-1,sizeof(head));
    129         for(int i=1; i<=n; i++)
    130         {
    131             scanf("%lld",&cost);
    132             if(cost>0)
    133             {
    134                 add(s,i,cost);
    135                 ans+=cost;
    136             }
    137             else add(i,t,-cost);
    138         }
    139         for(int i=1; i<=m; i++)
    140         {
    141             scanf("%lld%lld",&u,&v);
    142             add(u,v,INT_MAX);
    143         }
    144         memset(dep,0,sizeof(dep));
    145         long long int flow=dinic(s,t);
    146         cot=0;
    147         dfs(s);
    148         printf("%lld ",cot-1);
    149         printf("%lld
    ",ans-flow);
    150     }
    151     return 0;
    152 }
    View Code
  • 相关阅读:
    Linux系统调用
    Linux的中断 & 中断和异常的区别
    system v和posix的共享内存对比 & 共享内存位置
    epoll里面mmap释疑
    提高网络效率的总结
    推荐相关学习 & 典型算法、典型特征、典型推荐系统框架
    最大似然法理解
    调试多线程 & 查死锁的bug & gcore命令 & gdb对多线程的调试 & gcore & pstack & 调试常用命令
    内存屏障 & Memory barrier
    锁相关知识 & mutex怎么实现的 & spinlock怎么用的 & 怎样避免死锁 & 内核同步机制 & 读写锁
  • 原文地址:https://www.cnblogs.com/lthb/p/4485876.html
Copyright © 2011-2022 走看看