• Open-Pit Mining


    Description

    Open-pit mining is a surface mining technique of extracting rock or minerals from the earth by their removal from an open pit or borrow. Open-pit mines are used when deposits of commercially useful minerals or rocks are found near the surface. Automatic Computer Mining (ACM) is a company that would like to maximize its profits by open-pit mining. ACM has hired you to write a program that will determine the maximum profit it can achieve given the description of a piece of land.

    Each piece of land is modelled as a set of blocks of material. Block i has an associated value (vi), as well as a cost (ci), to dig that block from the land. Some blocks obstruct or bury other blocks. So for example if block i is obstructed by blocks j and k, then one must first dig up blocks j and k before block i can be dug up. A block can be dug up when it has no other blocks obstructing it.

    Input

    The first line of input is an integer N(1N200)N(1≤N≤200) which is the number of blocks. These blocks are numbered 1 through N. Then follow N lines describing these blocks. The ith such line describes block i and starts with two integers vi, ci denoting the value and cost of the ith block (0vi,ci200)(0≤vi,ci≤200) . Then a third integer 0miN10≤mi≤N−1 on this line describes the number of blocks that block i obstructs. Following that are mi distinct space separated integers between 1 and N (but excluding i) denoting the label(s) of the blocks that block i obstructs. You may assume that it is possible to dig up every block for some digging order. The sum of values mi over all blocks i will be at most 500.

    Output

    Output a single integer giving the maximum profit that ACM can achieve from the given piece of land.

    Sample Input

    5
    0 3 2 2 3
    1 3 2 4 5
    4 8 1 4
    5 3 0
    9 2 0
    

    Sample Output

    2
    

    Hint

    数论:网络流:最大权闭合子图,模板题

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<cmath>
    #include<algorithm>  
    using namespace std;  
    typedef long long ll;  
    const int N=1e6+5;  
    const int INF=0x3f3f3f3f;  
      
    struct node{  
        ll t,cap,flow,next;    
    }e[N];  
    int head[N],cur[N],cnt; 
    void init(){  
        memset(head,-1,sizeof(head));  
        cnt=0;  
    }  
    void add(int u,int v,ll cap)  
    {  
        e[cnt]=node{v,cap,0,head[u]};  
        head[u]=cnt++;  
        e[cnt]=node{u,0,0,head[v]};    
        head[v]=cnt++;  
    }  
    int d[N];   
    bool bfs(int s,int t)   //O(n+m)  
    {  
        memset(d,0,sizeof(d));  
        queue<int>q;  
        q.push(s);  
        d[s]=1;  
        while(!q.empty())  
        {  
            int u=q.front();q.pop();  
            for(int i=head[u];~i;i=e[i].next)  
            {  
                int v=e[i].t;  
                if(d[v]==0&&e[i].cap-e[i].flow>0)  
                {  
                    d[v]=d[u]+1;  
                    q.push(v);  
                }  
            }  
        }  
        return d[t]>0;   
    }  
    ll dfs(int s,int t,ll minedge)  
    {  
        if(s==t)return minedge;  
        ll flow=0;    
        for(int &i=cur[s];~i;i=e[i].next)  
        {  
            int v=e[i].t;  
            if(d[v]==d[s]+1&&e[i].cap-e[i].flow>0)  
            {  
                ll temp=dfs(v,t,min(minedge-flow,e[i].cap-e[i].flow));  
                e[i].flow+=temp;    
                e[i^1].flow-=temp;  
                flow+=temp;  
                if(flow==minedge)return flow;  
            }  
        }  
        if(flow==0)d[s]=0;    
        return flow;  
    }  
    ll dinic(int s,int t) 
    {  
        ll maxflow=0;  
        while(bfs(s,t))     
        {  
            memcpy(cur,head,sizeof(head));   
            maxflow+=dfs(s,t,INF);  
        }  
        return maxflow;  
    }  
    int pro[220];  
    int main()  
    {  
        int n,u,v,x,k;  
        init();  
        scanf("%d",&n);  
        for(int i=1;i<=n;i++)  
        {  
            scanf("%d%d%d",&u,&v,&k);  
            pro[i]=u-v;  
            while(k--){  
                scanf("%d",&x);  
                add(x,i,INF);  
            }  
        }  
        ll sum=0;  
        for(int i=1;i<=n;i++)  
        {  
            if(pro[i]>0){  
                add(0,i,pro[i]);  
                sum+=pro[i];  
            }  
            else if(pro[i]<0)add(i,n+1,-pro[i]);  
        }  
        int ans=dinic(0,n+1);  
        cout<<sum-ans<<endl;  
        return 0;  
    }  




  • 相关阅读:
    动态规划(DP),模拟
    递推,动态规划(DP),字符串处理,最佳加法表达式
    递归,动态规划,找最短路径,Help Jimmy
    动规,模拟,递推,最长公共子序列
    递归,递推,记忆化搜索,空间优化(数字三角形)
    递归,记忆化搜索,(棋盘分割)
    递归,搜索,回溯,最优路径(线段)
    web前端开发初学者必看的学习路线(附思维导图)
    一位资深程序员大牛给予Java初学者的学习路线建议
    假如时光倒流,我会这么学习Java
  • 原文地址:https://www.cnblogs.com/csushl/p/9386545.html
Copyright © 2020-2023  润新知