zoukankan      html  css  js  c++  java
  • [NOI2010]海拔 平面图转对偶图 最小割

    题解:

    首先,我们不难猜到高度只有 $0$ 或 $1$ 两种可能,而且高度为 0 的地区组成一个联通块,高度为 1 的地区组成一个联通块。只有这样,人们所耗费的体力才是最小的。
    得出这个结论,题目就成了求平面图的最小割。
    由于最大流等于最小割,网络流的做法是显然的,不过数据过大,不加优化是很难通过的。

    我们考虑将平面图转对偶图:
    我们知道平面图的最小割就等于对偶图的最短路。
    本题和 bzoj1002 狼抓兔子最显著的差别就是本题的边都是有向的,而狼抓兔子的边都是无向的。
    读者可以自己在草纸上画一画切割方案的 “极限” 情况,即最小割的形状是无规则的,发现对偶图中的每条边的方向恰好是原有向图的边的方向逆时针旋转 90 度。
    建完图跑最短路即可。 (spfa 的话最好加一些优化)

    Code:

    // luogu-judger-enable-o2
    #include<vector>
    #include<deque>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #include<string>
    using namespace std;
    
    typedef long long ll;
    void setIO(string a){
        freopen((a+".in").c_str(),"r",stdin),freopen((a+".out").c_str(),"w",stdout);
    }
    void end(){
        fclose(stdin),fclose(stdout);
    }
    const int maxn=1000002;
    int idx[600][600], n,s,t;
    int head[maxn],to[maxn],nex[maxn],val[maxn],edges;
    
    void add_edge(int u,int v,int c){
        nex[++edges]=head[u],head[u]=edges,to[edges]=v,val[edges]=c;
    }
    
    long long d[maxn];
    int inq[maxn];
    deque<int>Q;
    long long spfa()
    {
        memset(d,0x3f,sizeof(d));
        d[s]=0,inq[s]=1;Q.push_back(s);
        while(!Q.empty())
        {
            int u=Q.front();Q.pop_front();inq[u]=0;
            for(int v=head[u];v;v=nex[v])
                if(d[to[v]]>d[u]+val[v])
                {
                    d[to[v]]=d[u]+val[v];
                    if(!inq[to[v]])
                    {
                        inq[to[v]]=1;
                        if(Q.empty()||d[Q.front()]>=d[to[v]])Q.push_front(to[v]);
                        else Q.push_back(to[v]);
                    }
                }
        }
        return d[t];
    }
    int main(){
        //setIO("arrangement");
        scanf("%d",&n);
        int cnt=1;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j) idx[i][j]=++cnt;
    
        s=1,t=cnt+23;
        int cost;
        //down->up
        for(int i=1;i<=n;++i) scanf("%d",&cost),add_edge(idx[1][i],t,cost);
        for(int i=1;i<n;++i)
            for(int j=1;j<=n;++j) scanf("%d",&cost),add_edge(idx[i+1][j],idx[i][j],cost);
        for(int i=1;i<=n;++i) scanf("%d",&cost),add_edge(s,idx[n][i],cost);
    
        //left->right
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&cost),add_edge(s,idx[i][1],cost);
            for(int j=1;j<n;++j)scanf("%d",&cost),add_edge(idx[i][j],idx[i][j+1],cost);
            scanf("%d",&cost),add_edge(idx[i][n],t,cost);
        }
    
        //up->down
        for(int i=1;i<=n;++i) scanf("%d",&cost);
        for(int i=1;i<n;++i)
            for(int j=1;j<=n;++j)scanf("%d",&cost),add_edge(idx[i][j],idx[i+1][j],cost);
        for(int i=1;i<=n;++i) scanf("%d",&cost);
    
        //right->left
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&cost);
            for(int j=1;j<n;++j) scanf("%d",&cost),add_edge(idx[i][j+1],idx[i][j],cost);
            scanf("%d",&cost);
        }
        printf("%lld",spfa());
        //end();
        return 0;
    }
    

      

  • 相关阅读:
    CodeForces 492C Vanya and Exams (贪心)
    CodeForces 492A Vanya and Cubes
    如何设置 Windows 默认命令行窗口大小和缓冲区大小
    [MySQL] Data too long for column 'title' at row 1
    [转] Hibernate不能自动建表解决办法(hibernate.hbm2ddl.auto) (tables doesn't exist)
    CodeForces 489D Unbearable Controversy of Being (不知咋分类 思维题吧)
    Autofac官方文档翻译--二、解析服务--1解析参数传递
    Autofac官方文档翻译--一、注册组件--4组件扫描
    Autofac官方文档翻译--一、注册组件--3属性和方法注入
    Autofac官方文档翻译--一、注册组件--2传递注册参数
  • 原文地址:https://www.cnblogs.com/guangheli/p/9877375.html
Copyright © 2011-2022 走看看