• 【LOJ】#2384. 「HNOI2013」切糕


    题解

    神仙网络流啊……

    naive的我一直想把每个纵轴拆点,每个纵轴建R个点(大概是要跑费用流吧……)……然后第二个限制就gg了,什么也想不出来,菜啊TAT

    后来我发现大神们的建图都是,一个原点,一个汇点,一段长条,每一段就是一个点,流量是值,那么最小割就是最小值了,很神奇

    然后每相邻的两个纵轴z向z - D连一条边,z再向z + D连一条边

    感觉很神奇,后来我想了一下,这样并不能保证割了z之后一定割了相邻的[z - D,z+D]的点,而是可以保证,如果割错了这个割一定会被换掉!错误的答案是有限的,重复的错误不会出现……所以,最后就是正确的答案了呗。。。

    最小割保证了答案最小

    代码

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define MAXN 70005
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    template<class T>
    void read(T &res) {
        res = 0;char c = getchar();T f = 1;
        while(c < '0' || c > '9') {
    	if(c == '-') f = -1;
    	c = getchar();
        }
        while(c >= '0' && c <= '9') {
    	res = res * 10 + c - '0';
    	c = getchar();
        }
        res = res * f;
    }
    template<class T>
    void out(T x) {
        if(x < 0) {x = -x;putchar('-');}
        if(x >= 10) out(x / 10);
        putchar('0' + x % 10);
    }
    struct node {
        int to,next,cap;
    }E[4000005];
    int head[MAXN],sumE = 1,S,T,last[MAXN],Ncnt;
    int dis[MAXN],gap[MAXN],P,Q,R,D;
    int val[45][45][45],MK[45][45][45];
    int dx[] = {0,-1};
    int dy[] = {-1,0};
    void add(int u,int v,int c) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        E[sumE].cap = c;
        head[u] = sumE;
    }
    void addtwo(int u,int v,int c) {
        add(u,v,c);add(v,u,0);
    }
    int sap(int u,int aug) {
        if(u == T) return aug;
        int flow = 0;
        for(int i = last[u] ; i ; last[u] = i = E[i].next) {
    	int v = E[i].to;
    	if(E[i].cap) {
    	    if(dis[v] + 1 == dis[u]) {
    		int t = sap(v,min(aug - flow,E[i].cap));
    		flow += t;
    		E[i].cap -= t;
    		E[i ^ 1].cap += t;
    		if(flow == aug) return flow;
    		if(dis[S] >= T) return flow;
    	    }
    	}
        }
        --gap[dis[u]];if(!gap[dis[u]]) dis[S] = T;
        ++gap[++dis[u]];last[u] = head[u];
        return flow;
    }
    void Solve() {
        read(P);read(Q);read(R);
        read(D);
        for(int i = 1 ; i <= R ; ++i) {
    	for(int j = 1 ; j <= P ; ++j) {
    	    for(int k = 1 ; k <= Q ; ++k) {
    		read(val[j][k][i]);
    	    }
    	}
        }
        S = ++Ncnt;
        T = P * Q * (R + 1) + 10;
        for(int i = 1 ; i <= P ; ++i) {
    	for(int j = 1 ; j <= Q ; ++j) {
    	    ++Ncnt;addtwo(S,Ncnt,0x7fffffff);
    	    for(int k = 1 ; k <= R; ++k) {
    		++Ncnt;
    		MK[i][j][k] = Ncnt;
    		addtwo(Ncnt - 1,Ncnt,val[i][j][k]);
    	    }
    	    addtwo(Ncnt,T,0x7fffffff);
    	}
        }
        for(int i = 1 ; i <= P ; ++i) {
    	for(int j = 1 ; j <= Q ; ++j) {
    	    for(int h = 0 ; h <= 1 ; ++h) {
    		int tx = i + dx[h],ty = j + dy[h];
    		if(tx <= 0 || ty <= 0) continue;
    		for(int k = 1 ; k <= R ; ++k) {
    		    if(k - D >= 1) addtwo(MK[i][j][k],MK[tx][ty][k - D],0x7fffffff);
    		    if(k + D <= R) addtwo(MK[tx][ty][k + D],MK[i][j][k],0x7fffffff);
    		}
    	    }
    	}
        }
        for(int i = 1 ; i <= T ; ++i) last[i] = head[i];
        int ans = 0;
        while(dis[S] < T) ans += sap(S,0x7fffffff);
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    
  • 相关阅读:
    LF.25.K Smallest In Unsorted Array
    LC.102. Binary Tree Level Order Traversal
    LF.236.Search Insert Position
    发生错误 1069 sqlserver
    manualresetevent的用法学习
    xml selectnodes
    Flask 路由 , 初始化 , 配置Config , 蓝图BluePrint , 装饰器
    Python垃圾回收机制
    Odoo 动作Action
    Odoo 权限简介
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9176008.html
Copyright © 2020-2023  润新知