【网络流24题16】数字梯形问题
2018-02-03 20:45
381 查看
题面传送机
Little Knowledge
求最大果断最大费用流最大费用流就只是在最小费用流的基础上把价值都取相反数
Sol
这道题是由三道小题组成的(长沙中考数学第24题的感觉=m=)那我们就以解数学题的步骤写
首先列出条件(读入)
然后逐小题分析 , 分为下代码的solve1 solve2 solve3
然后就做辅助线了(建图)
分三种:
①solve1:
(i) 建立超源(S)汇(E)点
(ii) 为了保证不相交 把每个点拆成两个 并连有向边 i.a -> i.b 流量为1 费用为i的值
(iii) S与梯形的顶部m个点连有向边 S -> i.a 流量为1 费用为0(因为要从每一个顶边点出发)
(iiii) 底部点与E连有向边 i.b -> E 流量为 1 费用为 0
(iiiii) 每个点和其能到的点连有向边 流量为 1 费用为 0
②solve2:
(i) 建立超源(S)汇(E)点
(ii) 因为可以点相交 不拆点了
(iii) S与顶部m个节点连有向边 流量为 1 费用为 0
(iiii) 底部点与E相连 流量为 INF 费用为 底部点值
(iiii) 每个点和其能到的点连有向边 流量为 1 费用为 这个点的值
③solve3:
(i) 建立超源(S)汇(E)点
(ii) 这次修改建立在solve2上
(iii) 将除了连起点的边(因为要从每个起点引出一条线)的容量都改成INF就可以完美解决边相交了
Code
#include <iostream> #include <cstdio> #include <cctype> #include <cstring> #define inc(i) (i = -(~i)) #define dec(i) (i = ~(-i)) using namespace std; namespace fast { inline char Getchar() { static char buf[100001] , *p1 = buf , *p2 = buf; return p1 == p2 && (p2 = (p1 = buf) + fread(buf , 1 , 100000 , stdin) , p1 == p2) ? EOF : *p1 ++; } inline int read() { int num = 0; char c = 0; while(!isdigit(c)) c = Getchar(); while(isdigit(c)) num = num * 10 + c - '0' , c = Getchar(); return num; } } using namespace fast; const int M = 30000 + 7 , N = 500 + 7 , INF = 1e9 + 7; int n , m , Value , S , E , Order[30][30] , Total , Cost , Dep , k; int Head , Node[M] , W[M] , Co[M] , tot = 1 , Next[M]; inline void Add(int u , int v , int w , int c) { Next[inc(tot)] = Head[u] , Head[u] = tot , W[tot] = w , Co[tot] = -c , Node[tot] = v; Next[inc(tot)] = Head[v] , Head[v] = tot , W[tot] = 0 , Co[tot] = c , Node[tot] = u; } inline void in() { m = read() , n = read(); for(int i = 1 ; i <= n ; inc(i)) { for(int j = 1 ; j <= m + i - 1 ; inc(j)) inc(Total) , Value[Total] = read() , Order[i][j] = Total; } S = (Total << 1) + 1 , E = S + 1; } inline void Build1() { for(int i = 1 ; i <= Total ; inc(i)) Add(i , i + Total , 1 , Value[i]); for(int i = 1 ; i <= m ; inc(i)) Add(S , Order[1][i] , 1 , 0); for(int i = 1 ; i <= m + n - 1 ; inc(i)) Add(Order [i] + Total , E , 1 , 0); for(int i = 1 ; i < n ; inc(i)) for(int j = 1 ; j <= m + i - 1 ; inc(j)) { Add(Order[i][j] + Total , Order[i + 1][j] , 1 , 0); Add(Order[i][j] + Total , Order[i + 1][j + 1] , 1 , 0); } } inline void Build2() { for(int i = 1 ; i <= m ; inc(i)) Add(S , Order[1][i] , 1 , 0); for(int i = 1 ; i <= m + n + 1 ; inc(i)) Add(Order [i] , E , INF , Value[Order [i]]); for(int i = 1 ; i <= n ; inc(i)) for(int j = 1 ; j <= m + i - 1 ; inc(j)) { Add(Order[i][j] , Order[i + 1][j] , 1 , Value[Order[i][j]]); Add(Order[i][j] , Order[i + 1][j + 1] , 1 , Value[Order[i][j]]); } } inline void Build3() { for(int i = 1 ; i <= m ; inc(i)) Add(S , Order[1][i] , 1 , 0); for(int i = 1 ; i <= m + n - 1 ; inc(i)) Add(Order [i] , E , INF , Value[Order [i]]); for(int i = 1 ; i < n ; inc(i)) for(int j = 1 ; j <= m + i - 1 ; inc(j)) { Add(Order[i][j] , Order[i + 1][j] , INF , Value[Order[i][j]]); Add(Order[i][j] , Order[i + 1][j + 1] , INF , Value[Order[i][j]]); } } struct Queue { int Que[N * 10] , l , r; inline void cls() {l = 100 , r = 99;} inline int top() {return Que[l];} inline void push(int x) {Que[inc(r)] = x;} inline bool full() {return r >= l;} inline void pop() {inc(l);} }Q; bool inq , book ; inline bool SPFA() { memset(inq , 0 , sizeof(inq)); memset(Dep , 127 , sizeof(Dep)); int Big = Dep[E]; Dep[E] = 0; Q.cls() , Q.push(E); int u , v; while(Q.full()) { u = Q.top(); Q.pop(); for(int i = Head[u] ; i ; i = Next[i]) { v = Node[i]; if(W[i ^ 1] && Dep[v] > Dep[u] - Co[i]) { Dep[v] = Dep[u] - Co[i]; if(!inq[v]) { inq[v] = 1; Q.push(v); } } inq[u] = 0; } } return Dep[S] < Big; } inline int DFS(int u , int lastc) { if(u == E) return lastc; int Now = 0 , Flow , v; book[u] = 1; for(int i = Head[u] ; i ; i = Next[i]) { int v = Node[i]; if(!book[v] && W[i] && Dep[u] - Co[i] == Dep[v]) { Flow = DFS(v , min(lastc - Now , W[i])); if(Flow) { W[i] -= Flow; W[i ^ 1] += Flow; Now += Flow; Cost += Flow * Co[i]; if(Now == lastc) break; } } } return Now; } inline void Max_Flow() { int Ans = 0 , Flow; while(SPFA()) { if(!DFS(S , INF + 1)) break; memset(book , 0 , sizeof(book)); } } inline void Clear() { tot = 1 , Cost = 0; memset(Head , 0 , sizeof(Head)); } int main() { in(); Build1(); Max_Flow(); printf("%d\n" , -Cost); Clear(); Build2(); Max_Flow(); printf("%d\n" , -Cost); Clear(); Build3(); Max_Flow(); printf("%d" , -Cost); return 0; }
相关文章推荐
- 网络流24题16. 数字梯形问题
- 数字梯形问题[网络流24题之16]
- 网络流16数字梯形问题
- 网络流16数字梯形问题
- [网络流24题 #16]数字梯形问题
- 【网络流24题-16】数字梯形问题
- 【网络流24题-16】数字梯形问题 费用流
- [网络流24题] 16 数字梯形(最大权不相交路径 ,最小费用最大流)
- [网络流24题]数字梯形问题
- 线性规划与网络流24——数字梯形问题
- 【网络流24题】No.16 数字梯形问题 (不相交路径 最大费用流)
- [网络流24题] 数字梯形问题
- 网络流24题 -No.16 数字梯形问题
- 线性规划与网络流24题之数字梯形问题 最大权不相交路径
- 【网络流24题】数字梯形问题
- 网络流二十四题之十六 —— 数字梯形问题(DIGIT)
- 网络流与线性规划24题03最小路径覆盖问题
- 网络流24题之T1——飞行员配对方案问题
- 网络流24题1 飞行员配对方案问题
- 骑士共存问题[网络流24题之24]