BZOJ_1497_[NOI2006]_最大获利(最大流+最大权闭合图)

描述



共n个站点,给出建立每个站点所需要的花费.现在有m个客户需要开通服务,每个客户需要有两个站点,客户给钱.问最大利润是多少.

分析



要选一个客户,就必须要选他所需的两个站点,这样有约束关系的,可以用最大权闭合图做.

胡伯涛的论文<最小割模型在信息学竞赛中的应用>:

http://wenku.baidu.com/link?url=AwU_F4lYPSxxzmOrAZpL0t6lCMWjIVbuAXI59EKPbqEj7gpw0VRhhrGDU4BbOVFNGlVRt0KLZ6QrCAszJIT-TBfPV8jJ8fCTFdA4rTa3VdS

讲得挺详细,就是看起来有点费劲...

把客户和站点都看做点,客户是正权值,站点是负权值.要有客户就必须有站点,所以边由客户连向站点,表示如果客户被选中,他所需的两个站点也一定被选中.

1.站点连向汇点,容量是站点的花费的绝对值;

2.客户连向源点,容量是客户给的钱;

3.每个客户连向他所需的两个站点,容量是INF.

然后跑最大流即可.

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#define rep(i,n) for(int i=0;i<(n);i++)
#define for1(i,a,n) for(int i=(a);i<=(n);i++)
#define read(a) a=getnum()
#define print(a) printf("%d\n",a)
#define CC(i,a) memset(i,a,sizeof(i))
using namespace std;

const int maxn=5005,maxm=50005,INF=0x7fffffff;
int n,m,sumw;
int cost[maxn],level[maxn+maxm],iter[maxn+maxm];
struct edge { int to,cap,rev; };
vector <edge> g[maxn+maxm];

inline int getnum()
{
    int r=0,k=1; char c;
    for(c=getchar();c<‘0‘||c>‘9‘;c=getchar()) if(c==‘-‘) k=-1;
    for(;c>=‘0‘&&c<=‘9‘;c=getchar()) r=r*10+c-‘0‘;
    return r*k;
}

void add_edge(int from,int to,int cap)
{
    g[from].push_back((edge) { to,cap,g[to].size() });
    g[to].push_back((edge) { from,0,g[from].size()-1 });
}

void bfs(int s)
{
    CC(level,-1);
    level[s]=0;
    queue <int> q;
    q.push(s);
    while(!q.empty())
    {
        int t=q.front(); q.pop();
        rep(i,g[t].size())
        {
            edge e=g[t][i];
            if(level[e.to]<0&&e.cap>0)
            {
                level[e.to]=level[t]+1;
                q.push(e.to);
            }
        }
    }
}

int dfs(int v,int t,int f)
{
    if(v==t) return f;
    for(int &i=iter[v];i<g[v].size();i++)
    {
        edge &e=g[v][i];
        if(e.cap>0&&level[e.to]>level[v])
        {
            int d=dfs(e.to,t,min(f,e.cap));
            if(d>0)
            {
                e.cap-=d;
                g[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}

int max_flow(int s,int t)
{
    int flow=0;
    bfs(s);
    while(level[t]>0)
    {
        CC(iter,0);
        int f;
        while((f=dfs(s,t,INF))>0) flow+=f;
        bfs(s);
    }
    return flow;
}

void init()
{
    read(n); read(m);
    for1(i,1,n)
    {
        read(cost[i]);
        add_edge(i,n+m+1,cost[i]);
    }
    for1(i,1,m)
    {
        int a,b,c;
        read(a); read(b); read(c);
        add_edge(0,n+i,c);
        add_edge(n+i,a,INF);
        add_edge(n+i,b,INF);
        sumw+=c;
    }
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("prof.in","r",stdin);
    freopen("prof.out","w",stdout);
#endif
    init();
    print(sumw-max_flow(0,n+m+1));

#ifndef ONLINE_JUDGE
    fclose(stdin);
    fclose(stdout);
    system("prof.out");
#endif
    return 0;
}
时间: 2024-11-09 05:01:09

BZOJ_1497_[NOI2006]_最大获利(最大流+最大权闭合图)的相关文章

【TYVJ】QQ农场(最大流+最大权闭合图)

http://tyvj.cn/Problem_Show.aspx?id=1338 时间才排到rank7,还不快啊囧.isap我常数都写得那么小了... 最大权闭合图看我另一篇博文吧 此题很明显的模型. 首先我们先染色,使整个图黑白相间,其中我们只需要在黑色点向对应的上下左右白色节点连边,很明显,这些节点都有权值,我们需要求的是最大权,那么就按我的博文那样来做即可. 用sum-最小割就是答案. #include <cstdio> #include <cstring> #include

POJ_2987_Firing(最大流+最大权闭合图)

描述 http://poj.org/problem?id=2987 要炒员工鱿鱼,炒了一个人,他的下属一定被炒.给出每个人被炒后公司的收益(负值表示亏损),问怎样炒公司收益最大,以及这种方法炒了几个人.(先输出人数) 分析 求最大收益是用最大权闭合图.要炒一个人,他的下属也要被炒,那么边由上司连向下属,求最大权闭合图即可. 求炒了几个人实际是就是求先前求出来的那个最大权闭合图中点的个数.最大权闭合图对应的是最小割,而最小割中的边都是满流的,所以从源点出发无法到达闭合图的补集(即T),并且由于是闭

最大权闭合图 &amp;&amp; 【BZOJ】1497: [NOI2006]最大获利

最大权闭合图详细请看胡伯涛论文<最小割模型在信息学竞赛中的应用>,我在这里截图它的定义以及一些东西. 假设我们有一个图,点集的出边都是连到点集的,那么称这个为闭合图.现在这些点集都有个权值,我们要选择某个闭合图使得权值最大. 回到此题: 最大获利这一题,我们可以这样看,用户群和中转站为带权的点集,用户群的权为收益,中转站的权为负的成本,即0-成本,用户群向其中两个中转站连弧,那么这个就是一个闭合图. 我们要求这个闭合图的权值和最大,即最大收益,那么就能转移到上面的求最大权闭合图的做法去了. 做

BZOJ 1497 JZYZOJ 1344 [NOI2006]最大获利 网络流 最大权闭合图

http://www.lydsy.com/JudgeOnline/problem.php?id=1497 http://172.20.6.3/Problem_Show.asp?id=1344 思路:(最大权闭合图的思路相同) 将所有的用户群获利(正值)作为一个点连一条权值为获利值的边到st点,将所有的建站消耗(输入的是正值但是是在获利中减去的所以实质还是负值)作为一个点连一条权值为消耗值的边到ed点,再将每个用户群点和其依赖的建站点连一条权值为无穷的边,求st到ed的最大流. 此时,所求的最大获

[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}

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

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

【wikioi】1907 方格取数3(最大流+最大权闭合子图)

这题我一开始想到的是状压,看到n<=30果断放弃. 然后也想到了黑白染色,然后脑残了,没想到怎么连边. 很简单的一题 黑白染色后,每个点向四周连边,容量为oo,然后如果是黑(白)节点,源连一条边,容量为权值:如果是白(黑)节点,连一条边到汇,容量为权值. 最后答案为所有格子权值和-最大流(其实是最小割) ps:(其实就是之前做过的qq农场 囧..http://www.cnblogs.com/iwtwiioi/p/3893519.html 为什么这样做参考我以前写的博文(http://www.cn

【NOI2006】最大获利

[问题描述] 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU 集团旗下的CS&T 通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究.站址勘测.最优化等项目.     在前期市场调查和站址勘测之后,公司得到了一共N 个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第i个通讯中转站需要的成本为Pi(1≤i≤N).

【BZOJ-1497】最大获利 最大流

1497: [NOI2006]最大获利 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 3800  Solved: 1848[Submit][Status][Discuss] Description 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU集团旗下的CS&T通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究.站址勘测.最优化等项目.在前期市场调查和站址勘测之后,公司得