标签:
这题算是平面图上最大流/最小割比较经典的一题了吧。。
周冬的论文《两极相通——浅析最大最小定理在信息学竞赛中的应用》中给出了详细的解释和证明。
平面图上的最大流/最小割等于它对偶图上的最短路(大致是这个意思吧)。
把每个三角形作为点,有公共边就连边,有上边界和右边界的与源点连边,有左边界或下边界的与终点连边,然后跑一遍最短路即可。
注意n=1和m=1的情况要特判!
#include <queue> #include <vector> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; const size_t Max_V(2000050); const size_t Max_E(6000050); const unsigned int Up(1), Down(2); typedef pair<unsigned int, size_t> pil; void Get_Val(unsigned int &ret) { ret = 0; char ch; while ((ch = getchar()), (ch > ‘9‘ || ch < ‘0‘)) ; do { (ret *= 10) += ch - ‘0‘; } while ((ch = getchar()), (ch >= ‘0‘ && ch <= ‘9‘)); } void Special(const unsigned int &a) { unsigned int Ans(0X7F7F7F7FU); unsigned int Temp; for (unsigned int flag = 1;flag != a;++flag) { Get_Val(Temp); Ans = min(Ans, Temp); } printf("%u", Ans); } size_t N, M; size_t S, T; unsigned int Total; unsigned int Head[Max_V]; unsigned int To[Max_E], Next[Max_E], Weight[Max_E]; inline unsigned int Get_Point(const size_t &i, const size_t &j, const unsigned int &location) { return (((i - 1) * M + j - 1) << 1) + location; } inline void Add_Edge(const size_t &s, const size_t &t, const unsigned int &w) { ++Total; To[Total] = t, Weight[Total] = w; Next[Total] = Head[s], Head[s] = Total; } void init() { Get_Val(N), Get_Val(M); unsigned int w; if (N == 1) { Special(M); exit(0); } if (M == 1) { Special(N); exit(0); } --N, --M; S = (N * M << 1) + 1; T = (N * M << 1) + 2; for (size_t i = 0;i <= N;++i) for (size_t j = 1;j <= M;++j) { Get_Val(w); if (i == 0) { Add_Edge(Get_Point(1, j, Up), S, w); Add_Edge(S, Get_Point(1, j, Up), w); continue; } if (i == N) { Add_Edge(Get_Point(N, j, Down), T, w); Add_Edge(T, Get_Point(N, j, Down), w); continue; } Add_Edge(Get_Point(i, j, Down), Get_Point(i + 1, j, Up), w); Add_Edge(Get_Point(i + 1, j, Up), Get_Point(i, j, Down), w); } for (size_t i = 1;i <= N;++i) for (size_t j = 0;j <= M;++j) { Get_Val(w); if (j == 0) { Add_Edge(Get_Point(i, 1, Down), T, w); Add_Edge(T, Get_Point(i, 1, Down), w); continue; } if (j == M) { Add_Edge(Get_Point(i, j, Up), S, w); Add_Edge(S, Get_Point(i, j, Up), w); continue; } Add_Edge(Get_Point(i, j, Up), Get_Point(i, j + 1, Down), w); Add_Edge(Get_Point(i, j + 1, Down), Get_Point(i, j, Up), w); } for (size_t i = 1;i <= N;++i) for (size_t j = 1;j <= M;++j) { Get_Val(w); Add_Edge(Get_Point(i, j, Up), Get_Point(i, j, Down), w); Add_Edge(Get_Point(i, j, Down), Get_Point(i, j, Up), w); } } unsigned int Dist[Max_V]; bool Done[Max_V]; unsigned int dijkstra() { memset(Dist, 0X7F, sizeof(Dist)); priority_queue<pil, vector<pil>, greater<pil> > Q; Dist[S] = 0; Q.push(pil(0, S)); size_t Top; while (Q.size()) { Top = Q.top().second; Q.pop(); if (Done[Top]) continue; Done[Top] = true; for (size_t i = Head[Top];i;i = Next[i]) if (Dist[To[i]] > Dist[Top] + Weight[i]) { Dist[To[i]] = Dist[Top] + Weight[i]; Q.push(pil(Dist[To[i]], To[i])); } } return Dist[T]; } int main() { init(); printf("%u", dijkstra()); return 0; }
标签:
原文地址:http://www.cnblogs.com/Created-equal/p/5071154.html