• [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;
    }
    

      

  • 相关阅读:
    struts2之OGNL和struts2标签库和ValueStack对象
    struts2使用拦截器完成登陆显示用户信息操作和Struts2的国际化
    struts2的文件上传和文件下载
    jsp+servlet实现文件的上传和下载
    Ajax和JSON完成二级菜单联动的功能
    jxl的使用总结(java操作excel)
    Ajax异步验证登陆或者注册
    mydate97时间控件的使用
    Ckeditor一种很方便的文本编辑器
    搬家通知博文地址(将博客搬到CSDN)
  • 原文地址:https://www.cnblogs.com/guangheli/p/9877375.html
Copyright © 2020-2023  润新知