「NOI2010」海拔
最小割 #最短路 #对偶图
最优策略下不可能出现非整数的边权,一个自然的想法就是对原图建图然后求最小割
但是这不能满足时间限制
观察这个图,有建图方法,它一定是一个 平面图,考虑这样的建图:
对于每个被分出的格子,都在这个格子中建一个点表示它,然后对于两个格子之间的连边,这条边的权值就是与它相交的一条边的边权
对于这个图跑最短路,发现它的最短路等于原图的最小割
以上为 平面图最小割转化为对偶图最短路 的过程
平面图最小割转对偶图最短路
// Author: xiaruize #ifndef ONLINE_JUDGE bool start_of_memory_use; #else #define debug(x) #endif #include <bits/stdc++.h> using namespace std; #ifndef ONLINE_JUDGE clock_t start_clock = clock(); #endif namespace __DEBUG_UTIL__ { using namespace std; /* Primitive Datatypes Print */ void print(const char *x) { cerr << x; } void print(bool x) { cerr << (x ? "T" : "F"); } void print(char x) { cerr << '\'' << x << '\''; } void print(signed short int x) { cerr << x; } void print(unsigned short int x) { cerr << x; } void print(signed int x) { cerr << x; } void print(unsigned int x) { cerr << x; } void print(signed long int x) { cerr << x; } void print(unsigned long int x) { cerr << x; } void print(signed long long int x) { cerr << x; } void print(unsigned long long int x) { cerr << x; } void print(float x) { cerr << x; } void print(double x) { cerr << x; } void print(long double x) { cerr << x; } void print(string x) { cerr << '\"' << x << '\"'; } template <size_t N> void print(bitset<N> x) { cerr << x; } void print(vector<bool> v) { /* Overloaded this because stl optimizes vector<bool> by using _Bit_reference instead of bool to conserve space. */ int f = 0; cerr << '{'; for (auto &&i : v) cerr << (f++ ? "," : "") << (i ? "T" : "F"); cerr << "}"; } /* Templates Declarations to support nested datatypes */ template <typename T> void print(T &&x); template <typename T> void print(vector<vector<T>> mat); template <typename T, size_t N, size_t M> void print(T (&mat)[N][M]); template <typename F, typename S> void print(pair<F, S> x); template <typename T, size_t N> struct Tuple; template <typename T> struct Tuple<T, 1>; template <typename... Args> void print(tuple<Args...> t); template <typename... T> void print(priority_queue<T...> pq); template <typename T> void print(stack<T> st); template <typename T> void print(queue<T> q); /* Template Datatypes Definitions */ template <typename T> void print(T &&x) { /* This works for every container that supports range-based loop i.e. vector, set, map, oset, omap, dequeue */ int f = 0; cerr << '{'; for (auto &&i : x) cerr << (f++ ? "," : ""), print(i); cerr << "}"; } template <typename T> void print(vector<vector<T>> mat) { int f = 0; cerr << "\n~~~~~\n"; for (auto &&i : mat) { cerr << setw(2) << left << f++, print(i), cerr << "\n"; } cerr << "~~~~~\n"; } template <typename T, size_t N, size_t M> void print(T (&mat)[N][M]) { int f = 0; cerr << "\n~~~~~\n"; for (auto &&i : mat) { cerr << setw(2) << left << f++, print(i), cerr << "\n"; } cerr << "~~~~~\n"; } template <typename F, typename S> void print(pair<F, S> x) { cerr << '('; print(x.first); cerr << ','; print(x.second); cerr << ')'; } template <typename T, size_t N> struct Tuple { static void printTuple(T t) { Tuple<T, N - 1>::printTuple(t); cerr << ",", print(get<N - 1>(t)); } }; template <typename T> struct Tuple<T, 1> { static void printTuple(T t) { print(get<0>(t)); } }; template <typename... Args> void print(tuple<Args...> t) { cerr << "("; Tuple<decltype(t), sizeof...(Args)>::printTuple(t); cerr << ")"; } template <typename... T> void print(priority_queue<T...> pq) { int f = 0; cerr << '{'; while (!pq.empty()) cerr << (f++ ? "," : ""), print(pq.top()), pq.pop(); cerr << "}"; } template <typename T> void print(stack<T> st) { int f = 0; cerr << '{'; while (!st.empty()) cerr << (f++ ? "," : ""), print(st.top()), st.pop(); cerr << "}"; } template <typename T> void print(queue<T> q) { int f = 0; cerr << '{'; while (!q.empty()) cerr << (f++ ? "," : ""), print(q.front()), q.pop(); cerr << "}"; } /* Printer functions */ void printer(const char *) {} /* Base Recursive */ template <typename T, typename... V> void printer(const char *names, T &&head, V &&...tail) { /* Using && to capture both lvalues and rvalues */ int i = 0; for (size_t bracket = 0; names[i] != '\0' and (names[i] != ',' or bracket != 0); i++) if (names[i] == '(' or names[i] == '<' or names[i] == '{') bracket++; else if (names[i] == ')' or names[i] == '>' or names[i] == '}') bracket--; cerr.write(names, i) << " = "; print(head); if (sizeof...(tail)) cerr << " ||", printer(names + i + 1, tail...); else cerr << "]\n"; } /* PrinterArr */ void printerArr(const char *) {} /* Base Recursive */ template <typename T, typename... V> void printerArr(const char *names, T arr[], size_t N, V... tail) { size_t ind = 0; for (; names[ind] and names[ind] != ','; ind++) cerr << names[ind]; for (ind++; names[ind] and names[ind] != ','; ind++) ; cerr << " = {"; for (size_t i = 0; i < N; i++) cerr << (i ? "," : ""), print(arr[i]); cerr << "}"; if (sizeof...(tail)) cerr << " ||", printerArr(names + ind + 1, tail...); else cerr << "]\n"; } } #ifndef ONLINE_JUDGE #define debug(...) std::cerr << __LINE__ << ": [", __DEBUG_UTIL__::printer(#__VA_ARGS__, __VA_ARGS__) #define debugArr(...) std::cerr << __LINE__ << ": [", __DEBUG_UTIL__::printerArr(#__VA_ARGS__, __VA_ARGS__) #else #define debug(...) #define debugArr(...) #endif #define int long long #define ull unsigned long long #define ALL(a) (a).begin(), (a).end() #define pb push_back #define mk make_pair #define pii pair<int, int> #define pis pair<int, string> #define sec second #define fir first #define sz(a) int((a).size()) #define Yes cout << "Yes" << endl #define YES cout << "YES" << endl #define No cout << "No" << endl #define NO cout << "NO" << endl #define mms(arr, n) memset(arr, n, sizeof(arr)) #define rep(i, a, n) for (int i = (a); i <= (n); ++i) #define per(i, n, a) for (int i = (n); i >= (a); --i) int max(int a, int b) { if (a > b) return a; return b; } int min(int a, int b) { if (a < b) return a; return b; } const int INF = 0x3f3f3f3f3f3f3f3f; const int MOD = 1000000007; const int N = 3e5 + 10; int n; vector<pii> g[N]; int S, T; int dis[N]; int id(int x, int y) { return (x - 1) * n + y; } void solve() { cin >> n; n++; S = n * n + 1; T = n * n + 2; rep(i, 1, n) { rep(j, 1, n - 1) { int x; cin >> x; if (i == 1) g[S].push_back({id(i, j), x}); else if (i == n) g[id(i - 1, j)].push_back({T, x}); else g[id(i - 1, j)].push_back({id(i, j), x}); } } rep(i, 1, n - 1) { rep(j, 1, n) { int x; cin >> x; if (j == 1) g[id(i, j)].push_back({T, x}); else if (j == n) g[S].push_back({id(i, j - 1), x}); else g[id(i, j)].push_back({id(i, j - 1), x}); } } rep(i, 1, n) { rep(j, 1, n - 1) { int x; cin >> x; if (i == 1) g[id(i, j)].push_back({S, x}); else if (i == n) g[T].push_back({id(i - 1, j), x}); else g[id(i, j)].push_back({id(i - 1, j), x}); } } rep(i, 1, n - 1) { rep(j, 1, n) { int x; cin >> x; if (j == 1) g[T].push_back({id(i, j), x}); else if (j == n) g[id(i, j - 1)].push_back({S, x}); else g[id(i, j - 1)].push_back({id(i, j), x}); } } priority_queue<pii, vector<pii>, greater<pii>> q; q.push({0, S}); mms(dis, 0x3f); dis[S] = 0; while (!q.empty()) { auto [ds, x] = q.top(); q.pop(); if (ds != dis[x]) continue; for (auto [v, w] : g[x]) { if (dis[v] > dis[x] + w) { dis[v] = dis[x] + w; q.push({dis[v], v}); } } } cout << dis[T] << endl; } #ifndef ONLINE_JUDGE bool end_of_memory_use; #endif signed main() { freopen("altitude.in","r",stdin); freopen("altitude.out","w",stdout); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int testcase = 1; // cin >> testcase; while (testcase--) solve(); #ifndef ONLINE_JUDGE cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl; cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl; #endif return 0; }
本文作者:xiaruize's Blog
本文链接:https://www.cnblogs.com/xiaruize/p/18101836
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步