zoukankan      html  css  js  c++  java
  • 【BZOJ 1497】 [NOI2006]最大获利

    【链接】 我是链接,点我呀:)
    【题意】

    在这里输入题意

    【题解】

    最大权闭合子图的模板题。 每个人对两个物品有依赖。 则相当于m+n个点 这m个点是m个用户。 每个用户的权值是正的,为这个用户获得的利益。 然后每个基站对应n个点。这n个点上的权值都是负数的。 表示代价。

    然后就是最大权闭合子图问题了。

    套一个网络流模型

    源点s和每个人连流量为利益的边。
    每个基站和汇点t连流量为代价的绝对值的边。
    用户和基站对应的边。流量改为正无穷。

    这样这个网络的每个割(S,T)中 集合S除去汇点s剩下的点。
    就是原图的一个闭合子图了。
    (而且会发现每个闭合子图都能由一个割,一一对应

    分析一下会发现当求得最小割的时候。
    得到的闭合子图权值是最大的。
    而且这个闭合子图的权值就是所有正权的权值和减去最小割。

    参考 胡伯涛 《最小割模型在信息学竞赛中的应用》

    【代码】

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 5000;
    const int M = 50000;
    const int INF = 100*5000+50000*100 + 10;
    const int s = 0;
    
    struct node{
        int v,w,nex;
    }edge[(M*3+N+100)*2];
    
    int n,m,w[N+10],head[N+M+100],cur[N+M+100],k,d[N+M+100],t;
    int Q[N+M+100];
    
    void addEdge(int u,int v,int w){
        edge[k].v = v;
        edge[k].w = w;
        edge[k].nex = head[u];
        head[u] = k++;
    
        edge[k].v = u;
        edge[k].w = 0;
        edge[k].nex = head[v];
        head[v] = k++;
    }
    
    int bfs()
    {
        memset(d, 0, sizeof(d));
        d[s] = 1;
        int frnt = 0, rear = 0;
        Q[rear++] = s;
        while(frnt != rear)
        {
            int u = Q[frnt++];
            if(u == t) return 1;
            for(int i = head[u]; i != -1; i = edge[i].nex)
            {
                int to = edge[i].v, w = edge[i].w;
                if(w && d[to] == 0)
                {
                    d[to] = d[u] + 1;
                    if(to == t) return 1;
                    Q[rear++] = to;
                }
            }
        }
        return 0;
    }
    
    int dfs(int u, int maxflow)
    {
        if(u == t || !maxflow) return maxflow;
        int ret = 0;
        for(int& i = cur[u]; i != -1; i = edge[i].nex)
        {
            int to = edge[i].v, w = edge[i].w;
            if(w && d[to] == d[u]+1)
            {
                int f = dfs(to, min(maxflow-ret, w));
                edge[i].w -= f;
                edge[i^1].w += f;
                ret += f;
                if(ret == maxflow) return ret;
            }
        }
        return ret;
    }
    
    int Dicnic(){
        int ans = 0;
        while (bfs()==1){
            memcpy(cur,head,sizeof(head));
            ans+=dfs(0,INF);
        }
        return ans;
    }
    
    int main()
    {
        memset(head,255,sizeof head);
        cin >> n >> m;
        t = n+m+1;
        for (int i = 1;i <= n;i++) cin >> w[i];
        int ans = 0;
        for (int i = 1;i <= m;i++){
            int x,y,z;
            cin >> x >> y >> z;
            addEdge(i,m+x,INF);addEdge(i,m+y,INF);
            addEdge(0,i,z);
            ans+=z;
        }
        for (int i = 1;i <= n;i++) addEdge(m+i,m+n+1,w[i]);
        cout<<ans-Dicnic()<<endl;
        return 0;
    }
    
    
  • 相关阅读:
    Oracle 性能优化之一二
    要一直知道什么是最重要的
    c# 当引用类型作为方法的参数
    BI测试工具之跨数据库数据对比,支持oracle,sqlserver
    c#分页读取GB文本文件
    Merge compare columns when null
    Oracle常用plsql
    quick sort java version
    基于元数据的ETL系统
    Centos 6.5(64bit)上安装Vertica single node
  • 原文地址:https://www.cnblogs.com/AWCXV/p/9012337.html
Copyright © 2011-2022 走看看