码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-04-27 17:09:41      阅读:151      评论:0      收藏:0      [点我收藏+]

标签:

描述


共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;
}

 

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

标签:

原文地址:http://www.cnblogs.com/Sunnie69/p/5439403.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!