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-width:4px,fill-opacity:0.5 class id,id1,id2,id3,id4,id5,id6,id7,id8 className; linkStyle default fill:#fff,stroke:#f73,stroke-width: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;
}

posted @ 2019-05-24 14:53  zhangxianlong  阅读(297)  评论(0编辑  收藏  举报