LG P2046 [NOI2010]海拔(平面图转对偶图,最短路)

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/qq_35950004/article/details/88546790

题目
之前看有人写博客:NOI2010原题重测中他第一次打最小割转最短路就A了。
学习了(200行的)最左转线和点定位之后,我深深的膜拜他。
今日一见此题。
好像我也可以。
不用最左转线,不用点定位。
直接人类智慧。
注意反向边也需要连,最小割不一定只包含一个方向的边。
注意0边也需要连,因为不连等同于inf。

AC Code:

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#define maxn 300005
#define maxm 2000005
using namespace std;

int n;
int info[maxn],Prev[maxm],to[maxm],cst[maxm],cnt_e=1;
void Node(int u,int v,int c){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v,cst[cnt_e]=c; }
void Line(int u,int v,int c){ Node(u,v,c); }

int dis[maxn];
bool usd[maxn];

int main()
{
    scanf("%d",&n);
    int S = n * n + 1 , T = n * n + 2;
    for(int i=1;i<=n+1;i++)
        for(int j=1;j<=n;j++)
        {
            int x;
            scanf("%d",&x);
			if(i == 1) Line(S,(i-1)*n+j,x);
			else if(i == n+1) Line((i-2)*n+j,T,x);
			else Line((i-2)*n+j,(i-1)*n+j,x);
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n+1;j++)
        {
            int x;
            scanf("%d",&x);
			if(j == 1) Line((i-1)*n+j,T,x);
			else if(j == n+1) Line(S,(i-1)*n+j-1,x);
			else Line((i-1)*n+j,(i-1)*n+j-1,x);
        }
    
    
    for(int i=1;i<=n+1;i++)
        for(int j=1;j<=n;j++)
        {
            int x;
            scanf("%d",&x);
			if(i == 1) Line((i-1)*n+j,S,x);
			else if(i == n+1) Line(T,(i-2)*n+j,x);
			else Line((i-1)*n+j,(i-2)*n+j,x);
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n+1;j++)
        {
            int x;
            scanf("%d",&x);
			if(j == 1) Line(T,(i-1)*n+j,x);
			else if(j==n+1) Line((i-1)*n+j-1,S,x);
			else Line((i-1)*n+j-1,(i-1)*n+j,x);
        }
    
    priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > >q;
    memset(dis,0x3f,sizeof dis);
    q.push(make_pair(0,S)),dis[S] = 0;
    for(int now;!q.empty();)
    {
        now = q.top().second , q.pop();
        if(usd[now]) continue;
        usd[now] = 1;
        for(int i=info[now];i;i=Prev[i])
            if(dis[to[i]] > dis[now] + cst[i])
            {
                dis[to[i]] = dis[now] + cst[i];
                q.push(make_pair(dis[to[i]],to[i]));
            }
    }
    printf("%d\n",dis[T]);
}

猜你喜欢

转载自blog.csdn.net/qq_35950004/article/details/88546790