• [BZOJ 2007] 海拔


    Link:https://www.lydsy.com/JudgeOnline/problem.php?id=2007

    Algorithm:

    由于起点高度为0,终点高度为1,明显没有必要有比1大的点

    因此得到结论:原图仅由0和1构成,且0和1不交错排布

    那么所有对答案的贡献都来自于0和1的分界线,那么就将问题转化为求最小割

    但点数过多,网络流明显会超时,那么此时就要用到对偶图了

    如果一个图是平面图(无边的相交),则可以将面化为点,构建对偶图,如下图所示

    这样就能把求平面图的最小割问题  -------->  求其对偶图的ST最短路   妙啊

    由于此题为有向图,每条边的从S到T还是从T到S的性质不能改变

    因此原左右、上下边现在由S到T,而右左、下上由T到S

    Code:

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> P;
    
    const int MAXN=500+10;
    int num[MAXN][MAXN],n,s,t;
    vector<P> G[MAXN*MAXN];
    
    ll dist[MAXN*MAXN];
    queue<int> que;
    
    inline int read()
    {
        char ch;int num,f=0;
        while(!isdigit(ch=getchar())) f|=(ch=='-');
        num=ch-'0';
        while(isdigit(ch=getchar())) num=num*10+ch-'0';
        return f?-num:num;
    }
    
    void add_edge(int x,int y,int val)
    {
        G[x].push_back(P(y,val));
    }
    
    int main()
    {
        n=read();s=0;t=n*n+1;  //预处理每个点在对偶图中的编号
        for(int i=1;i<=n;i++)
            num[0][i]=num[i][n+1]=s,num[i][0]=num[n+1][i]=t;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                num[i][j]=(i-1)*n+j;
        
        int x;    
        for(int i=0;i<=n;i++)  //构图
            for(int j=1;j<=n;j++)
                x=read(),add_edge(num[i][j],num[i+1][j],x);
        for(int i=1;i<=n;i++)
            for(int j=0;j<=n;j++)
                x=read(),add_edge(num[i][j+1],num[i][j],x);
        for(int i=0;i<=n;i++)
            for(int j=1;j<=n;j++)
                x=read(),add_edge(num[i+1][j],num[i][j],x);
        for(int i=1;i<=n;i++)
            for(int j=0;j<=n;j++)
                x=read(),add_edge(num[i][j],num[i][j+1],x);
        
        memset(dist,0x3f,sizeof(dist));  //SPFA求最短路
        que.push(s);dist[s]=0;
        while(!que.empty())
        {
            int u=que.front();que.pop();
            for(int i=0;i<G[u].size();i++)
            {
                P t=G[u][i];int v=t.first;
                if(dist[v]>dist[u]+t.second)
                    dist[v]=dist[u]+t.second,que.push(v);
            }
        }
        cout << dist[t];
        return 0;
    }

    1、熟悉平面图  到   对偶图的转换

    2、最小割问题可以在对偶图中用最短路算法解决

    3、对偶图建图

    预处理出每个点的编号,将最外层(0、N+1)留给S和T

    要确定每条边是从S到T还是T到S的性质不改变

  • 相关阅读:
    公用表表达式(CTE)的递归调用
    c# 如何让tooltip显示文字换行
    实战 SQL Server 2008 数据库误删除数据的恢复
    SQL SERVER数据库中 是否可以对视图进行修改删除
    asp.net中实现文件批量上传
    sql server 2008学习2 文件和文件组
    sql server 2008学习3 表组织和索引组织
    sql server 2008学习4 设计索引的建议
    sql server 2008学习10 存储过程
    .net 调用 sql server 自定义函数,并输出返回值
  • 原文地址:https://www.cnblogs.com/newera/p/9056243.html
Copyright © 2020-2023  润新知