zoukankan      html  css  js  c++  java
  • [NOI2010] 海拔

    题目链接:戳我
    看到输出格式。。。。如果有小数的话为什么需要保留到整数呢。。。所以——

    并没有小数!我们可以认为每个点的海拔要么是1要么是0.然后求最小割就可以了!

    至于为什么要么是1要么是0?蒟蒻yy的证明:既然是求出来最小割,如果差是1的话就可以割掉这条边了,这样对最小值(比如说x)加权为1。如果不是差1,那么显然对于这个点,我们就不能割一条边了事了,至少需要割掉两条边(比如说x,x',其中x'>x),这样虽然每个边的值加权是个小于一的小数,但是总和加起来还是没有前面的小。

    既然是最小割,我们直接求不就好了!

    数据范围有点大,显然裸的最小割跑不过去。这时候我们就要优化了!启用平面图转对偶图,用dijkstra+priority_queue优化求最短路。

    最后注意建图方式,源点在左下角,汇点在右上角,这样才能用最短路求出来最小割。(别像我智障地一开始把源点建到了左上,汇点右下,还以为自己什么都没写错qwqwq)

    连边的话,显然是原图向右的连成向下的,向下的连成向右的,向左的连成向上的,向上的连成向左的,这样才能求出来最小割。(原图向左向上的边别不连!因为有可能最小割比较曲折。。。。。)

    此外还有一个建图小技巧吧。。从yyb dalao那里学的,直接用数组存序号就行了。。。这样就不用每次都写诸如(i-1)*m+j的东西了。。。
    代码如下:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define S 0
    #define T cnt+1
    #define MAXN 4000010
    using namespace std;
    int n,m,t,cur,cnt;
    int dis[MAXN],done[MAXN],head[MAXN],id[510][510];
    struct Node
    {
        int u,d;
        friend bool operator <(struct Node x,struct Node y)
            {return x.d>y.d;}
    };
    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;}
    inline void dij(int s,int t)
    {
        priority_queue<Node>q;
        memset(dis,0x3f,sizeof(dis));
        memset(done,0,sizeof(done));
        q.push((Node){s,0});dis[s]=0;
        while(!q.empty())
        {
            int u=q.top().u; q.pop();
            if(done[u]) continue;
            done[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int v=edge[i].to;
                if(dis[u]+edge[i].dis<dis[v])
                    dis[v]=dis[u]+edge[i].dis,q.push((Node){v,dis[v]});
            }
        }
    }
    int main()
    {
        #ifndef ONLINE_JUDGE
        freopen("ce.in","r",stdin);
        #endif
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                id[i][j]=++cnt;
        for(int i=1;i<=n;i++) id[0][i]=id[i][0]=S,id[i][n+1]=id[n+1][i]=T;
        for(int i=1;i<=n+1;i++) 
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&cur);
                add(id[i-1][j],id[i][j],cur);
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n+1;j++)
            {
                scanf("%d",&cur);
                add(id[i][j-1],id[i][j],cur);
            }
        for(int i=0;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                scanf("%d",&cur);
                add(id[i+1][j],id[i][j],cur);
            }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n+1;j++)
            {
                scanf("%d",&cur);
                add(id[i][j],id[i][j-1],cur);
            }
        dij(S,T);
        printf("%d
    ",dis[T]);
        return 0;
    }
    
  • 相关阅读:
    ansible-playbook启动的多种方式
    git版本控制
    特征工程
    特征工程:图像特征提取和深度学习
    tensorflow数据读取机制tf.train.slice_input_producer 和 tf.train.batch 函数
    浙大版《C语言程序设计(第3版)》题目集 练习2-9 整数四则运算 (10 分)
    浙大版《C语言程序设计(第3版)》题目集 练习2-8 计算摄氏温度 (10 分)
    浙大版《C语言程序设计(第3版)》题目集 练习2-6 计算物体自由下落的距离 (5 分)
    浙大版《C语言程序设计(第3版)》题目集 练习2-4 温度转换 (5 分)
    浙大版《C语言程序设计(第3版)》题目集 练习2-3 输出倒三角图案 (5 分)
  • 原文地址:https://www.cnblogs.com/fengxunling/p/10298583.html
Copyright © 2011-2022 走看看