• HNOI2013 切糕


    题目链接:戳我

    最小割的一种常见模型。
    题目可以转化为:给定一个立方体,它被分成pqr个格子,每个格子中都有一个数字,相邻地选择数字,每一行每一列都要选择一个数字。要求这些数字和最小。

    建图就是建r+1层,然后这些边的权值是对应位置的数字权值。从每一个点(第z层)向它旁边四个纵轴连一条指向第z-d层的有向边(这样可以限制旁边纵轴上选择的点的层数>=z-d,但是我们想要的是在>=z-d的同时还<=z+d。这个不用担心,因为它旁边的纵轴也会有和它同样的操作连上去有向边,在层数>z+d的时候,它通过指向>z的点的有向边依然可以流向汇点——所以说这样就限制住了层数)。

    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define S 0
    #define T cnt+1
    #define MAXN 100010
    #define INF 0x3f3f3f3f
    using namespace std;
    int P,Q,R,t=1,d,cnt;
    int head[MAXN],dep[MAXN],cur[MAXN],sum[50][50][50],id[50][50][50];
    struct Edge{int nxt,to,dis;}edge[MAXN<<1];
    
    inline void add(int from,int to,int dis)
    {
        edge[++t].nxt=head[from],edge[t].to=to,edge[t].dis=dis,head[from]=t;
        edge[++t].nxt=head[to],edge[t].to=from,edge[t].dis=0;head[to]=t;
    }
    
    inline bool bfs()
    {
        queue<int>q;
        memset(dep,0x3f,sizeof(dep));
        memcpy(cur,head,sizeof(head));
        q.push(S);dep[S]=0;
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(dep[v]==0x3f3f3f3f&&edge[i].dis)
                    dep[v]=dep[u]+1,q.push(v);
            }
        }
        if(dep[T]==0x3f3f3f3f) return false;
        return true;
    }
    
    inline int dfs(int x,int f)
    {
        if(!f||x==T) return f;
        int w,used=0;
        for(int i=cur[x];i;i=edge[i].nxt)
        {
            int v=edge[i].to;
            cur[x]=i;
            if(dep[v]==dep[x]+1&&(w=dfs(v,min(f,edge[i].dis))))
            {
                edge[i].dis-=w,edge[i^1].dis+=w;
                used+=w,f-=w;
                if(!f) break;
            }
        }
        return used;
    }
    
    inline int dinic()
    {
        int cur_ans=0;
        while(bfs()) cur_ans+=dfs(S,INF);
        return cur_ans;
    }
    
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce1.in","r",stdin);
        #endif
        scanf("%d%d%d",&P,&Q,&R);
        for(int z=1;z<=R+1;z++)
            for(int x=1;x<=P;x++)
                for(int y=1;y<=Q;y++)
                    id[x][y][z]=++cnt;
        scanf("%d",&d);
        for(int z=1;z<=R;z++)
            for(int x=1;x<=P;x++)
                for(int y=1;y<=Q;y++)
                    scanf("%d",&sum[x][y][z]);
        for(int z=1;z<=R+1;z++)
        {
            for(int x=1;x<=P;x++)
            {
                for(int y=1;y<=Q;y++)
                {
                    if(z==1) add(S,id[x][y][z],INF);//printf("[%d,%d] %d
    ",S,id[x][y][z],INF);
                    if(z==R+1) add(id[x][y][z],T,INF);//printf("[%d,%d] %d
    ",id[x][y][z],T,INF);
                    else add(id[x][y][z],id[x][y][z+1],sum[x][y][z]);//printf("[%d,%d] %d
    ",id[x][y][z],id[x][y][z+1],sum[x][y][z]);
                    if(z>d) 
                    {
                        if(y+1<=Q) add(id[x][y][z],id[x][y+1][z-d],INF);//printf("[%d,%d] %d
    ",id[x][y][z],id[x][y+1][z-d],INF);
                        if(y-1>=1) add(id[x][y][z],id[x][y-1][z-d],INF);//printf("[%d,%d] %d
    ",id[x][y][z],id[x][y-1][z-d],INF);
                        if(x+1<=P) add(id[x][y][z],id[x+1][y][z-d],INF);//printf("[%d,%d] %d
    ",id[x][y][z],id[x+1][y][z-d],INF);
                        if(x-1>=1) add(id[x][y][z],id[x-1][y][z-d],INF);//printf("[%d,%d] %d
    ",id[x][y][z],id[x-1][y][z-d],INF);
                    }
                }
            }
        }
        printf("%d
    ",dinic());
        return 0;
    }
    
  • 相关阅读:
    歌曲汇总
    赤道附近
    看樱花(也有很多其他花)
    线程池异常处理之重启线程处理任务
    ElasticSearch Index操作源码分析
    探究ElasticSearch中的线程池实现
    由字典树想到的
    ElasticSearch 启动时加载 Analyzer 源码分析
    Elasticsearch6.3.2启动过程源码阅读记录
    Elasticsearch High Level Rest Client 发起请求的过程分析
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10364618.html
Copyright © 2020-2023  润新知