OpenJudge 3765(最大权闭合图,最小割

题目大意:需要解雇若干人,解雇每个人有一个损失或收益,解雇一个人就必须结果他的所有下属,问最大收益。

思路:裸最大权闭合图问题,对于权值为q的点,负权向汇点连-p的边,正权源点向其连p的边,上下级关系上级向下级连oo的边,然后求最大流最小割,最大收益即为总正点权减最小割,需要裁员的人即为残余图中从源点可达的点。

参考:http://blog.csdn.net/scorpiocj/article/details/6085637

#include <bits/stdc++.h>
#define pb push_back
#define se second
#define fs first
#define sq(x) (x)*(x)
#define eps 0.000000001
#define LB lower_bound
#define IINF (1<<29)
#define LINF (1ll<<59)
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
const int maxv=5010;
struct EDGE{
    int to,rev;
    ll cap;
    EDGE(int t,ll c,int r):to(t),cap(c),rev(r){}
};
vector<EDGE> G[maxv];
void addedge(int from,int to,ll cap){
    G[from].pb(EDGE(to,cap,G[to].size()));
    G[to].pb(EDGE(from,0,G[from].size()-1));
}
int level[maxv];
queue<int> Q;
void bfs(int s){
    memset(level,-1,sizeof level);
    level[s]=0;
    Q.push(s);
    while(!Q.empty()){
        int v=Q.front();Q.pop();
        for(int i=0;i<G[v].size();i++){
            EDGE &e=G[v][i];
            if(level[e.to]==-1&&e.cap>0){
                level[e.to]=level[v]+1;
                Q.push(e.to);
            }
        }
    }
}
int iter[maxv];
ll dfs(int v,int t,ll f){
    if(v==t) return f;
    for(int &i=iter[v];i<G[v].size();i++){
        EDGE &e=G[v][i];
        ll d;
        if(e.cap>0&&level[e.to]>level[v]){
            d=dfs(e.to,t,min(e.cap,f));
            if(d>0){
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}
ll dinic(int s,int t){
    ll flow=0;
    for(;;){
        bfs(s);
        if(level[t]==-1){
            return flow;
        }
        ll f;
        memset(iter,0,sizeof iter);
        while((f=dfs(s,t,LINF))>0) flow+=f;
    }
}
int cc=0;
bool vis[maxv];
void cont(int v){
    cc++;
    vis[v]=1;
    for(int i=0;i<G[v].size();i++){
        EDGE &e=G[v][i];
        if(!vis[e.to]&&e.cap>0){
            cont(e.to);
        }
    }
}
const int s=5008,t=5009;
int n,m;
int pro[maxv];
int main(){
    freopen("/home/files/CppFiles/in","r",stdin);
    cin>>n>>m;
    ll sum=0;
    for(int i=1;i<=n;i++){
        ll p;
        scanf("%lld",&p);
        pro[i]=p;
        if(p>0){
            addedge(s,i,p);
            sum+=p;
        }
        else
            addedge(i,t,-p);
    }
    for(int i=0;i<m;i++){
        ll x,y;
        scanf("%lld%lld",&x,&y);
        addedge(x,y,LINF);
    }
    ll ans=sum-dinic(s,t);
    cont(s);
    cout<<cc-1<<" "<<ans<<endl;
}

时间: 2024-11-06 07:04:58

OpenJudge 3765(最大权闭合图,最小割的相关文章

最大权闭合图 最小割

闭合图为原图的一个子图, 满足任意一个节点的后继仍在闭合图中. 给原图的每个点以一个点权, 权值总和最大的闭合图称为最大权闭合图. 我们考虑利用最小割求解最大权闭合图. 首先, 为了权值最大, 我们贪心地将所有点权为正的点给选上, 但是这样可能会矛盾, 因为一个点权为正的点的后继可能点权为负. 我们考虑利用最小割, 减去最小的使方案合法的花费. 建立源点 S , 与 S 相连的意义是这个点被选择, 则初始的时候, 对于点权为正的点 i , 连边 (S, i, a[i]) . 建立汇点 T , 与

[luoguP2762] 太空飞行计划问题(最大权闭合图—最小割—最大流)

传送门 如果将每一个实验和其所对的仪器连一条有向边,那么原图就是一个dag图(有向无环) 每一个点都有一个点权,实验为收益(正数),仪器为花费(负数). 那么接下来可以引出闭合图的概念了. 闭合图是原图的一个点集,其中这个点集中每个点的出边所指向的点依然在这个点集中,那么这个点集就是个闭合图. 比如论文中的这个图: 在图 3.1 中的网络有 9 个闭合图(含空集):∅,{3,4,5},{4,5},{5},{2,4,5},{2,5},{2,3,4,5},{1,2,4,5},{1,2,3,4,5}

最大权闭合子图(最小割)

最大权闭合子图(最大流最小割) •参考资料 [1]最大权闭合子图 •权闭合子图 存在一个图的子图,使得子图中的所有点出度指向的点依旧在这个子图内,则此子图是闭合子图. 在这个图中有8个闭合子图:∅,{3},{4},{2,4},{3,4},{1,3,4},{2,3,4},{1,2,3,4} •最大权闭合子图 在一个图中每个点具有点权值,在他的所有闭合子途中点权之和最大的即是最大权闭合子图. •详解 最大权闭合子图 结论 最大权闭合子图权值  =  所有权值为正的权值之和  -  最大流 •步骤 建

【最大权闭合子图/最小割】BZOJ3438-小M的作物【待填】

[题目大意] 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子有1个(就是可以种一棵作物)(用1...n编号),现在,第i种作物种植在A中种植可以获得ai的收益,在B中种植可以获得bi的收益,而且有m种作物组合,第i个组合中的作物共同种在A中可以获得c1i的额外收益,共同总在B中可以获得c2i的额外收益,所以,小M很快地算出了种植的最大收益. [思路] 首先,如果没有组合方案应该怎么做呢?其实非常方便. 首先建立超级源点S和超级汇点T,S

bzoj 1497 [NOI2006]最大获利【最大权闭合子图+最小割】

不要被5s时限和50000点数吓倒!大胆网络流!我一个5w级别的dinic只跑了1s+! 看起来没有最大权闭合子图的特征--限制,实际上还是有的. 我们需要把中转站看成负权点,把p看成点权,把客户看成正权点,把c看成点权,然后把中转站点a.b作为客户点的依赖点 s点向所有正权点连边,流量为点权:所有负权点向t连边,流量为负点权(即正数!) 对于所有有依赖关系的点,由客户点向中转站点连边,流量为inf,也就是最大权闭合子图中的向其依赖点连边 连边的意义详见:http://www.cnblogs.c

HDU 4971 A simple brute force problem.(最小割,最大权闭合图)

http://acm.hdu.edu.cn/showproblem.php?pid=4971 A simple brute force problem. Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 182    Accepted Submission(s): 115 Problem Description There's a com

HDU 3061 Battle(最小割----最大权闭合图)

题目地址:HDU 3061 多校中遇到的最小割的最大权闭合模型花了一上午时间终于看懂啦. 最大权闭合图就是将一些互相有依赖关系的点转换成图,闭合图指的是在图中的每一个点的后继点都是在图内的. 还要明白简单割的概念,就是指所有的割边都与源点或汇点相连.然后让源点与正权点相连,汇点与负权点相连,权值均为其绝对值,有依赖关系的点连一条有向边,如果a必须在b的基础上,那么就连一条a->b的有向边,权值为INF.最后用所有正权值得和减去最小割的值就是答案. 具体证明可看胡伯涛大牛的国家队集训论文<最小割

noi 2006 最大收益 最大权闭合图转最小割转最大流

题意:一个公司有n个可以建造通讯战的地方,建造成本分别为pi,然后第i个公司会选择使用通讯站ai与bi,使用费用是ci,然后问这个通讯公司怎么建站能够获利最大.(净获利=总收益-总成本): 网上看到一篇题解,直接说这是个最小割,求最小割然后总收益-最小割就是了.这种题解就是一点用也没有,为什么是最小割,总得解释解释吧,撂下结论就跑了,这种题解写来何用. 之后查了一篇国家集训队的论文<最小割模型在信息学竞赛中的应用>才明白原来是最大权闭合图转的最小割,至于为什么能转成最小割,自己去看论文的证明吧

POJ 2987 Firing (最大权闭合图,最小割)

http://poj.org/problem?id=2987 Firing Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 7865   Accepted: 2377 Description You've finally got mad at "the world's most stupid" employees of yours and decided to do some firings. You're n