• CF1146G Zoning Restrictions 最小割


    CF1146G Zoning Restrictions 最小割

    题意:
    你准备在一条街上建房子。这条街上共有nn个地方可以用来建房子,每个房子高度最高为h。若你建了一个高度为aa的房子,那你将得到a^2的收益。但是这条街有mm个分区限制。具体来说,对于第ii个分区限制,若你在l_il 到r_ir 这段区间内最高的房子的高度严格大于了x_ix ,那你将受到c_ic 的罚款。求你的最大收益(房子收益-−罚款)
    原题链接:http://codeforces.com/problemset/problem/1146/G
    思路:
    可以dp,这里讲一个最小割的网络流做法。
    首先将每个点的0~h串起来,用h*h-利益将边转化成损失,每个点建图大致如下。跑出最小割之后h*h*n-maxflow就是答案了。

    graph LR; id((S)) --inf--> id1((A0)) id1((A0))--h*h-0-->id2((A1)) id2((A1))--h*h-1-->id3((A2)) id3((A2))--h*h-4-->id4((A3)) id4((A3))--h*h-9-->id5((...)) id3((A2))--inf-->id6((lim1)) id6((lim1))--lim1-->id7((T)) id4((A3))--inf-->id8((lim2)) id8((lim2))--lim2-->id7((T)) classDef className fill:#f9f,stroke:#333,stroke-4px,fill-opacity:0.5 class id,id1,id2,id3,id4,id5,id6,id7,id8 className; linkStyle default fill:#fff,stroke:#f73,stroke-2px,fill-opacity:1.0;

    说的不是很清楚,看代码即可。
    代码:

    #include<bits/stdc++.h>
    #define FIO std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    const ll inf=1e9+7;
    const int MAXN = 3010;//点数的最大值
    const int MAXM = 10010;//边数的最大值
    const int INF = 1e9+7;
    struct Edge
    {
        int to,next,cap,flow;
    } edge[MAXM]; //注意是 MAXM
    int tol;
    int head[MAXN];
    void init()
    {
        tol = 2;
        memset(head,-1,sizeof(head));
    }
    void addedge(int u,int v,int w,int rw = 0)
    {
        edge[tol].to = v;
        edge[tol].cap = w;
        edge[tol].flow = 0;
        edge[tol].next = head[u];
        head[u] = tol++;
        edge[tol].to = u;
        edge[tol].cap = rw;
        edge[tol].flow = 0;
        edge[tol].next = head[v];
        head[v] = tol++;
    }
    int Q[MAXN];
    int dep[MAXN],cur[MAXN],sta[MAXN];
    bool bfs(int s,int t,int n)
    {
        int front = 0,tail = 0;
        memset(dep,-1,sizeof(dep[0])*(n+1));
        dep[s] = 0;
        Q[tail++] = s;
        while(front < tail)
        {
            int u = Q[front++];
            for(int i = head[u]; i != -1; i = edge[i].next)
            {
                int v = edge[i].to;
                if(edge[i].cap > edge[i].flow && dep[v] == -1)
                {
                    dep[v] = dep[u] + 1;
                    if(v == t)return true;
                    Q[tail++] = v;
                }
            }
        }
        return false;
    }
    int dinic(int s,int t,int n)
    {
        int maxflow = 0;
        while(bfs(s,t,n))
        {
            for(int i = 0; i < n; i++)cur[i] = head[i];
            int u = s, tail = 0;
            while(cur[s] != -1)
            {
                if(u == t)
                {
                    int tp = INF;
                    for(int i = tail-1; i >= 0; i--)
                        tp = min(tp,edge[sta[i]].cap-edge[sta[i]].flow);
                    maxflow += tp;
                    for(int i = tail-1; i >= 0; i--)
                    {
                        edge[sta[i]].flow += tp;
                        edge[sta[i]^1].flow -= tp;
                        if(edge[sta[i]].cap-edge[sta[i]].flow == 0)
                            tail = i;
                    }
                    u = edge[sta[tail]^1].to;
                }
                else if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to])
                {
                    sta[tail++] = cur[u];
                    u = edge[cur[u]].to;
                }
                else
                {
                    while(u != s && cur[u] == -1)
                        u = edge[sta[--tail]^1].to;
                    cur[u] = edge[cur[u]].next;
                }
            }
        }
        return maxflow;
    }
    
    int n,m,h,l,r,x,c;
    inline int idx(int x,int y){
        return x*(h+1)+(y+1);
    }
    int main(){
        FIO;
        int tt;
        cin>>n>>h>>m;
        int ans=h*h*n;
        init();
        int s=0,t=n*(h+1)+m+1;
        for(int i=0;i<n;i++){
            addedge(s,idx(i,0),inf);
            for(int j=0;j<h;j++){
                addedge(idx(i,j),idx(i,j+1),h*h-j*j);
            }
        }
        for(int i=1;i<=m;i++){
            cin>>l>>r>>x>>c;
            for(int j=l;j<=r;j++){
                if(x<h)addedge(idx(j-1,x+1),n*(h+1)+i,inf);
            }
            addedge(n*(h+1)+i,t,c);
        }
        cout<<ans-dinic(s,t,t+1)<<endl;
    	return 0;
    }
    
    
  • 相关阅读:
    leetcode 3.回文数
    vue系列 url的hash和HTML5的history
    并发编程 六 支付接口并发
    python+uvicorn+fastapi (一) 认识与第一个DEMO
    并发编程四(4) 线程同步 Condition
    vue系列 vuerouter安装配置呈现DEMO
    leetcode 6.有效的括号
    leetcode 1.两数之和
    AIRTEST 剑与远征 推图脚本
    leetcode 2.整数反转
  • 原文地址:https://www.cnblogs.com/zhangxianlong/p/10918172.html
Copyright © 2020-2023  润新知