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\n",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
posted @ 2019-11-10 16:08  RikukiIX  阅读(159)  评论(0编辑  收藏  举报