1. 程式人生 > >【BZOJ】2007: [Noi2010]海拔(平面圖轉對偶圖)

【BZOJ】2007: [Noi2010]海拔(平面圖轉對偶圖)

using targe line problem max 最小 mem AR pop

題目

傳送門: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; }

【BZOJ】2007: [Noi2010]海拔(平面圖轉對偶圖)