2007: [Noi2010]海拔

2007: [Noi2010]海拔

https://www.lydsy.com/JudgeOnline/problem.php?id=2007

 

分析:

  平面图最小割。

  S在左下,T在右上,从S到T的一个路径使得路径右下方全是1,左上方全是0。

  一个问题:每个点的高度只能是0/1,所以有些边是一定不能选的,就让它连向S,不影响。

 

代码:

  1 /*
  2 平面图最小割 
  3 */
  4 #include<cstdio>
  5 #include<algorithm>
  6 #include<cstring>
  7 #include<iostream>
  8 #include<cctype>
  9 #include<queue>
 10 using namespace std;
 11 typedef long long LL;
 12 
 13 inline int read() {
 14     int x = 0, f = 1; char ch = getchar(); for (; !isdigit(ch); ch=getchar()) if (ch=='-') f = -1;
 15     for (; isdigit(ch); ch=getchar()) x = x * 10 + ch - '0'; return x * f;
 16 }
 17 
 18 const int N = 250010;
 19 struct Edge{
 20     int to, w, nxt;
 21     Edge() {}
 22     Edge(int a,int b,int c) {to = a, w = b, nxt = c;}
 23 }e[2500100];
 24 struct Node{
 25     int u;
 26     LL dis;
 27     Node() {}
 28     Node(int a,LL b) {u = a, dis = b;}
 29     bool operator < (const Node &A) const {
 30         return dis > A.dis;
 31     }
 32 };
 33 int head[N];
 34 LL dis[N];
 35 int Enum, n;
 36 bool vis[N];
 37 priority_queue<Node> q;
 38 
 39 void add_edge(int u,int v,int w) {
 40     e[++Enum] = Edge(v, w, head[u]); head[u] = Enum;
 41 //    cout << u << " " << v << " " << w << '\n';
 42 }
 43 
 44 int get(int i,int j) {
 45     return (i - 1) * n + j;
 46 }
 47 
 48 int Dijkstra(int S,int T) {
 49     for (int i=0; i<=T; ++i) dis[i] = 1e18, vis[i] = false;
 50     dis[S] = 0;
 51     q.push(Node(S,0));
 52     Node now, nxt;
 53     while (!q.empty()) {
 54         now = q.top(); q.pop();
 55         int u = now.u;
 56         if (vis[u]) continue;
 57         vis[u] = true;
 58         for (int i=head[u]; i; i=e[i].nxt) {
 59             int v = e[i].to;
 60             if (dis[v] > dis[u] + e[i].w) {
 61                 dis[v] = dis[u] + e[i].w;
 62                 q.push(Node(v,dis[v]));
 63             }
 64         }
 65     }
 66     return dis[T];
 67 }
 68 
 69 int main() {
 70     n = read();
 71     int S = 0, T = n * n + 1;
 72     
 73     for (int i=1; i<=n+1; ++i) { // 左 -> 右, 下 -> 上 
 74         for (int j=1; j<=n; ++j) {
 75             int w = read();
 76             if (i == 1) add_edge(get(i, j), T, w);
 77             else if (i == n + 1) add_edge(S, get(i - 1, j), w);
 78             else add_edge(get(i, j), get(i - 1, j), w);
 79         }
 80     }
 81     
 82     for (int i=1; i<=n; ++i) { // 上 -> 下 , 左 -> 右 
 83         for (int j=1; j<=n+1; ++j) {
 84             int w = read();
 85             if (j == 1) add_edge(S, get(i, j), w);
 86             else if (j == n + 1) add_edge(get(i, j - 1), T, w);
 87             else add_edge(get(i, j - 1), get(i, j), w);
 88         }
 89     }
 90     
 91     for (int i=1; i<=n+1; ++i) { // 右 -> 左 , 上 -> 下 
 92         for (int j=1; j<=n; ++j) {
 93             int w = read();
 94             if (i == 1) add_edge(T, get(i, j), w);
 95             else if (i == n + 1) add_edge(get(i - 1, j), S, w);
 96             else add_edge(get(i - 1, j), get(i, j), w);
 97         }
 98     }
 99     
100     for (int i=1; i<=n; ++i) { // 下 -> 上 , 右 - > 左 
101         for (int j=1; j<=n+1; ++j) {
102             int w = read();
103             if (j == 1) add_edge(get(i, j), S, w);
104             else if (j == n + 1) add_edge(T, get(i, j - 1), w);
105             else add_edge(get(i, j), get(i, j - 1), w);
106         }
107     }
108     printf("%d",Dijkstra(S, T));
109     return 0;
110 }

 

posted @ 2018-08-24 15:23  MJT12044  阅读(173)  评论(2编辑  收藏  举报