codeforces863F Almost Permutation cost flow

Topic Portal

Meaning of the questions:

  Constructed a number of columns, numbers $ 1 within the ~ scope n $ a, $ / sum ^ requirements {n} _ {i} count (i) ^ {2} $ minimum, $ COUNT (i) $ mean number of columns in the i the number of occurrences. And the number of columns to two types of conditions are satisfied, one is $ a_i-> a_j $ all greater than v, as well as $ a_i-> a_j $ all less than v.

Ideas:

  First of all, we can put constraints into the upper and the lower limit value of a certain position, and then the position can fill all numbers corresponding to both sides of a building capacity, and then each of the n digital building capacity to sink 1 of side, one costing $ 1,3,5, ......, 2 * j-1 $, so after the construction side, if a number is selected twice, and just get the prefix is ​​the square of the number of occurrences.

 

#pragma GCC optimize (2)
#pragma G++ optimize (2)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<bits/stdc++.h>
#include<cstdio>
#include<vector>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dep(i,b,a) for(int i=b;i>=a;i--)
#define clr(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define pii pair<int,int >
using namespace std;
typedef long long ll;
const int maxn=200010;
const int inf=0x3f3f3f3f;
ll rd()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
#include<bits/stdc++.h>
#define CLR(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int MAXN = 1010;
const int MAXM = 20010;
const int INF = 0x3f3f3f3f;
struct Edge {
    int to, next, cap, flow, cost;

} edge[MAXM];
struct pp{
    int u,v,c,w;
}in[MAXN];
int head[MAXN], tol;
int pre[MAXN], dis[MAXN];
bool vis[MAXN];
int N=MAXN-2;
int n,q,l[MAXN],r[MAXN];
void init() {

    tol = 0;
    memset(head, -1, sizeof(head));

}
void addv(int u, int v, int cap, int cost) {
    edge[tol].to = v;
    edge[tol].cap = cap;
    edge[tol].cost = cost;
    edge[tol].flow = 0;
    edge[tol].next = head[u];
    head[u] = tol++;
    edge[tol].to = u;
    edge[tol].cap = 0;
    edge[tol].cost = -cost;
    edge[tol].flow = 0;
    edge[tol].next = head[v];
    head[v] = tol++;

}
bool spfa(int s, int t) {
    queue<int>q;
    clr(dis,INF);
    clr(vis,0),clr(pre,-1);

    dis[s] = 0;
    vis[s] = true;
    q.push(s);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        vis[u] = false;
        for (int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].to;

            if (edge[i].cap > edge[i].flow && dis[v] > dis[u] + edge[i].cost) {
                dis[v] DIS = [U] + edge[i].cost;
                pre [V] = I;
                 IF (! {VIS [V]) 
                    VIS [V] = to true ; 
                    q.push (V); 

                } 

            } 

        } 

    } 
    IF (pre [T] == - . 1 ) return  to false ;
     the else  return  to true ; 

} 
// returns the maximum flow, cost is a minimum cost stored 
int minCostMaxflow ( int S, int T, int & cost) {
     int flow = 0 ;
    cost = 0;
    while (spfa(s, t)) {
        int Min = INF;
        for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) {
            if (Min > edge[i].cap - edge[i].flow)
                Min = edge[i].cap - edge[i].flow;

        }
        for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]) {
            edge[i].flow += Min;
            edge[i ^ 1].flow -= Min;
            cost += edge[i].cost * Min;

        }
        flow += Min;

    }
    return flow;

}
int main(){
    cin>>n>>q;
    init();
    int S=0,T=2*n+1;
    rep(i,1,n){
        addv(S,i,1,0);
        r[i]=n;
        l[i]=1;
        rep(j,1,n){
            addv(i+n,T,1,2*j-1);
        }
    }
    int flag=1;
    while(q--){
        int op,x,y,v;
        scanf("%d%d%d%d",&op,&x,&y,&v);
        if(op==1){
            rep(i,x,y){
                l[i]=max(l[i],v);
            }
        }else{
            rep(i,x,y){
                r[i]=min(r[i],v);
            }
        }
    }
    rep(i,1,n){
        if(l[i]>r[i]){
            flag=0;
            break;
        }
        rep(j,l[i],r[i]){
            addv(i,j+n,1,0);
        }
    }
    if(flag==0){
        puts("-1");
        return 0;
    }
    int c;
    minCostMaxflow(S,T,c);
    cout<<c<<endl;
    
} 

 

Guess you like

Origin www.cnblogs.com/mountaink/p/11609772.html