【BZOJ】2007: [Noi2010]海拔(平面图转对偶图)

题目

传送门:QWQ

分析

左上角是0,右下角是1。那么大概整张图是由0 1构成的。

那么我们要找到0和1的分界线,值就是最小割。

然后变成求原图最小割。

考虑到此题是平面图,那么就转成对偶图跑最短路。

完了。

总结:以后看到数据在$ nlog(n) $范围内的题,给的图是方格图,给的边还方方正正,那么多半是平面图转对偶图。

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn=510*510;
vector<int> G[maxn];
struct Edge{ int u,v,dis; };
vector<Edge> edges;
struct HeapNode{
    int x,dis;
    bool operator <(const HeapNode& a) const{ return dis>a.dis; }
};
void link(int u,int v,int dis){
    edges.push_back((Edge){u,v,dis}); //edges.push_back((Edge){v,u,dis});
    int m=edges.size(); G[u].push_back(m-1);
}
int d[maxn],vis[maxn];
priority_queue<HeapNode> que; 
int dijkstra(int s,int t){
    memset(d,127,sizeof(d));
    d[s]=0; que.push((HeapNode){s,0}); //vis[s]=1;
    while(!que.empty()){
        HeapNode x=que.top(); que.pop();
        if(vis[x.x]) continue; vis[x.x]=1;
        int u=x.x;
        for(int i=0;i<G[u].size();i++){
            Edge& e=edges[G[u][i]];
            if(d[e.v]>d[u]+e.dis){
                d[e.v]=d[u]+e.dis;
                que.push((HeapNode){e.v,d[e.v]}); 
            }
        }
    }
    return d[t];
}
int num[505][505];
int main(){
    int n,x;scanf("%d",&n);
    int    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] = n * (i - 1) + j;
    for(int i=0;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&x),link(num[i][j] , num[i+1][j] , x);
    for(int i=1;i<=n;i++) for(int j=0;j<=n;j++) scanf("%d",&x),link(num[i][j+1] , num[i][j] , x);
    for(int i=0;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&x),link(num[i+1][j] , num[i][j] , x);
    for(int i=1;i<=n;i++) for(int j=0;j<=n;j++) scanf("%d",&x),link(num[i][j] , num[i][j+1] , x);
    printf("%d\n",dijkstra(s,t));
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/noblex/p/9161791.html
今日推荐