P2046 [NOI2010]海拔

题面

容易想到原图由海拔高度划分成两大连通块。

于是就可以套上最小割了。

由于点数过多,可以将网络流最小割转换为其对偶图最短路。

#include<bits/stdc++.h>
using namespace std;
int read()
{
    int x=0,f=1;    char ch=getchar();
    while(ch<'0'||ch>'9')    {if(ch=='-')    f=-1;    ch=getchar();}
    while(ch>='0'&&ch<='9')    {x=(x<<3)+(x<<1)+(ch^48);    ch=getchar();}
    return x*f;
}
int n,cnt=2;
int col[505][505],tot,dis[1000050];
int head[1000050],nex[2000050],ver[2000050],edg[2000050];
priority_queue<pair<int ,int > >q;
bool vis[1000050];
void add(int x,int y,int z)
{
    ++tot;nex[tot]=head[x];head[x]=tot;ver[tot]=y;edg[tot]=z;
}
void spfa()
{
    memset(dis,127/2,sizeof(dis));
    dis[1]=0;    q.push(make_pair(0,1));
    while(!q.empty())
    {
        int u=q.top().second;
        q.pop();    vis[u]=false;
        for(int i=head[u];i;i=nex[i])
        {
            int v=ver[i];
            if(dis[v]>dis[u]+edg[i])
            {
                dis[v]=dis[u]+edg[i];
                if(!vis[v])
                {
                    vis[v]=true;
                    q.push(make_pair(-dis[v],v));
                }
            }
        }
    }
}
int main()
{
    n=read();
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n;++j)
            col[i][j]=++cnt;
    for(int i=1;i<=n;++i)
        col[i][0]=col[n+1][i]=1;
    for(int i=1;i<=n;++i)
        col[0][i]=col[i][n+1]=2;
    for(int i=1;i<=n+1;++i)
        for(int j=1;j<=n;++j)
            add(col[i][j],col[i-1][j],read());
    for(int i=1;i<=n;++i)
        for(int j=0;j<=n;++j)
            add(col[i][j],col[i][j+1],read());
    for(int i=0;i<=n;++i)
        for(int j=1;j<=n;++j)
            add(col[i][j],col[i+1][j],read());
    for(int i=1;i<=n;++i)
        for(int j=1;j<=n+1;++j)
            add(col[i][j],col[i][j-1],read());
    spfa();        printf("%d",dis[2]);
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/wyher/p/10991624.html