数字梯形问题(费用流)
费用流,拆点
//http://www.cnblogs.com/IMGavin/ #include <iostream> #include <stdio.h> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <map> #include <stack> #include <set> #include <bitset> #include <algorithm> using namespace std; typedef long long LL; #define gets(A) fgets(A, 1e8, stdin) const int INF = 0x3F3F3F3F, N = 1008, MOD = 1003, M = 2000000; const double EPS = 1e-6; int val[N][N]; struct Node{ int u, v, cap, cost; int next; }edge[M];//有向图,u到v的容量,费用 int tot; int head[N], pre[N], path[N], dis[N]; bool inq[N]; int m, n; void init(){ tot = 0; memset(head, -1, sizeof(head)); } void add(int u, int v, int cost, int cap){ edge[tot].u = u; edge[tot].v = v; edge[tot].cap = cap; edge[tot].cost = cost; edge[tot].next = head[u]; head[u] = tot++; edge[tot].u = v; edge[tot].v = u; edge[tot].cap = 0; edge[tot].cost = -cost; edge[tot].next = head[v]; head[v] = tot++; } bool SPFA(int st, int des){//计算最小费用 memset(inq, 0, sizeof(inq)); memset(dis, 0x3f, sizeof(dis)); queue <int> q; q.push(st); dis[st] = 0; inq[st] = true; while(!q.empty()){ int u = q.front(); q.pop(); inq[u] = false; for(int i = head[u]; ~i; i = edge[i].next){ int v = edge[i].v; if(edge[i].cap > 0 && dis[v] > dis[u] + edge[i].cost){ dis[v] = dis[u] + edge[i].cost; pre[v] = u; path[v] = i; if(!inq[v]){ inq[v] = true; q.push(v); } } } } return dis[des] < INF; } int EdmondsKarp(int st, int des){//最小费用最大流 int mincost = 0, flow = 0;//最小费用与流量 while(SPFA(st, des)){ int f = INF; for(int i = des; i != st; i = pre[i]){ if(f > edge[path[i]].cap){ f = edge[path[i]].cap; } } for(int i = des; i != st; i = pre[i]){ edge[path[i]].cap -= f; edge[path[i]^1].cap += f; } mincost += f * dis[des]; flow += f; } return mincost; } int cal1(){ init(); int tot = n * m + n * (n -1) / 2; int st = 0, des = tot * 2 + 1; for(int i = 0; i < n; i++){ for(int j = 0; j < m + i; j++){ int u = i * m + i * (i - 1) / 2 + j + 1; add(u, u + tot, -val[i][j], 1); } } for(int i = 0; i < n - 1; i++){ for(int j = 0; j < m + i; j++){ int u = i * m + i * (i - 1) / 2 + j + 1; int v = (i + 1) * m + i * (i + 1) / 2 + j + 1; add(u + tot, v, 0, 1); add(u + tot, v + 1, 0, 1); } } for(int i = 1; i <= m; i++){ add(st, i, 0, 1); } for(int i = 0; i < n + m - 1; i++){ int u = (n - 1) * m + (n - 1) * (n - 2) / 2 + i + 1; add(u + tot, des, 0, 1); } return -EdmondsKarp(st, des); } int cal2(){ init(); int tot = n * m + n * (n -1) / 2; int st = 0, des = tot * 2 + 1; for(int i = 0; i < n; i++){ for(int j = 0; j < m + i; j++){ int u = i * m + i * (i - 1) / 2 + j + 1; add(u, u + tot, -val[i][j], INF); } } for(int i = 0; i < n - 1; i++){ for(int j = 0; j < m + i; j++){ int u = i * m + i * (i - 1) / 2 + j + 1; int v = (i + 1) * m + i * (i + 1) / 2 + j + 1; add(u + tot, v, 0, 1); add(u + tot, v + 1, 0, 1); } } for(int i = 1; i <= m; i++){ add(st, i, 0, 1); } for(int i = 0; i < n + m - 1; i++){ int u = (n - 1) * m + (n - 1) * (n - 2) / 2 + i + 1; add(u + tot, des, 0, INF); } return -EdmondsKarp(st, des); } int cal3(){ init(); int tot = n * m + n * (n -1) / 2; int st = 0, des = tot * 2 + 1; for(int i = 0; i < n; i++){ for(int j = 0; j < m + i; j++){ int u = i * m + i * (i - 1) / 2 + j + 1; add(u, u + tot, -val[i][j], INF); } } for(int i = 0; i < n - 1; i++){ for(int j = 0; j < m + i; j++){ int u = i * m + i * (i - 1) / 2 + j + 1; int v = (i + 1) * m + i * (i + 1) / 2 + j + 1; add(u + tot, v, 0, INF); add(u + tot, v + 1, 0, INF); } } for(int i = 1; i <= m; i++){ add(st, i, 0, 1); } for(int i = 0; i < n + m - 1; i++){ int u = (n - 1) * m + (n - 1) * (n - 2) / 2 + i + 1; add(u + tot, des, 0, INF); } return -EdmondsKarp(st, des); } int main(){ while(cin >> m >> n){ for(int i = 0; i < n; i++){ for(int j = 0; j < m + i; j++){ scanf("%d", &val[i][j]); } } cout<<cal1()<<endl; cout<<cal2()<<endl; cout<<cal3()<<endl; } return 0; }