• bzoj2007/luoguP2046 海拔(平面图最小割转对偶图最短路)


    bzoj2007/luoguP2046 海拔(平面图最小割转对偶图最短路)

    题目描述:

    bzoj  luogu

    题解时间:

    首先考虑海拔待定点的$h$都应该是多少

    很明显它们都是$0$或$1$,并且所有$0$连成一块,所有$1$连成一块

    只有海拔交界线对答案有贡献,变成了最小割

    但是数据范围很明显不能直接跑网络流

    由于这是一个平面图,所以根据套路想到:

    平面图最小割=对偶图最小环=最外一块面积分成$S$和$T$跑最短路

    从左上角往右下角画一条线把外面一块分成$S$和$T$之后建图。

    但是要注意这张图上同一条边两个方向权值不同。

    那么建边也按照相同方向,即对应向右下方向的边的新建边为$S$->$T$方向,向左上的反之。

    然后就可以跑最短路了。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    typedef long long lint;
    namespace LarjaIX
    {
    const int N=511;
    int n,id[N][N];
    struct sumireko{int to,ne,w;}e[N*N*8];
    int he[N*N*2],ecnt;
    void addline(int f,int t,int w)
    {
        e[++ecnt].to=t,e[ecnt].w=w;
        e[ecnt].ne=he[f],he[f]=ecnt;
    }
    struct shion
    {
        int x;lint d;
        shion(){}
        shion(int x,lint d):x(x),d(d){}
        bool operator < (const shion &a)const{return d>a.d;}
    }stmp;
    priority_queue<shion>q;
    lint dis[N*N*2];
    bool vis[N*N*2];
    void dijkstra(int sp,int ep)
    {
        memset(dis,0x3f,sizeof(dis));
        q.push(shion(sp,dis[sp]=0));
        while(!q.empty())
        {
            stmp=q.top(),q.pop();
            int x=stmp.x;
            if(vis[x]) continue;vis[x]=1;
            for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)
            {
                if(dis[t]>dis[x]+e[i].w)
                {
                    dis[t]=dis[x]+e[i].w;
                    q.push(shion(t,dis[t]));
                }
            }
        }
        printf("%lld
    ",dis[ep]);
    }
    int wi;
    int maid()
    {
        #ifdef debug
        freopen("sample.in","r",stdin);
        freopen("debug.out","w",stdout);
        #endif
        scanf("%d",&n);
        for(int i=1;i<=n;i++)id[i][0]=id[n+1][i]=0,id[0][i]=id[i][n+1]=n*n+1;
        for(int i=1;i<=n;i++)for(int j=1;j<=n;j++) id[i][j]=(i-1)*n+j;
        for(int i=0;i<=n;i++)for(int j=1;j<=n;j++)
            scanf("%d",&wi),addline(id[i+1][j],id[i][j],wi);
        for(int i=1;i<=n;i++)for(int j=0;j<=n;j++)
            scanf("%d",&wi),addline(id[i][j],id[i][j+1],wi);
        for(int i=0;i<=n;i++)for(int j=1;j<=n;j++)
            scanf("%d",&wi),addline(id[i][j],id[i+1][j],wi);
        for(int i=1;i<=n;i++)for(int j=0;j<=n;j++)
            scanf("%d",&wi),addline(id[i][j+1],id[i][j],wi);
        dijkstra(0,n*n+1);
        return 0;
    }
    }
    int main(){return LarjaIX::maid();}
    View Code
  • 相关阅读:
    复利结对项目 增添
    结对编程-对队友的评价
    复利结对项目
    阅读《构造之法》第4章有感
    单元测试
    实验一 命令解释程序cmd的编写
    阅读《构造之法》1、2、3章有感
    复利计算
    实验总结
    汉堡包评价
  • 原文地址:https://www.cnblogs.com/rikurika/p/11830599.html
Copyright © 2020-2023  润新知