HDU 2686 Matrix && HDU 3376 Matrix Again(最大费用)
2017-08-16 17:21
387 查看
题目地址
题意:告诉你一个矩阵,每个点有它所代表的值,每个点都只能走一次,求从( 0,0)->(n-1,n-1)->(0,0)的最大值。(两题的写法完全一样,只是第二题数据范围加大了)
思路:其实就可以转化为两次从( 0,0)->(n-1,n-1)的最大费用,就是把除了源点和汇点( 0,0)以及(n-1,n-1)的其他边的容量置为1,他们置为2,然后只能向右或者向下走,按这个要求建边,再这样跑一边最大费用就好了
HDU 2686
HDU 3376
题意:告诉你一个矩阵,每个点有它所代表的值,每个点都只能走一次,求从( 0,0)->(n-1,n-1)->(0,0)的最大值。(两题的写法完全一样,只是第二题数据范围加大了)
思路:其实就可以转化为两次从( 0,0)->(n-1,n-1)的最大费用,就是把除了源点和汇点( 0,0)以及(n-1,n-1)的其他边的容量置为1,他们置为2,然后只能向右或者向下走,按这个要求建边,再这样跑一边最大费用就好了
HDU 2686
#include <iostream> #include <cstring> #include <string> #include <queue> #include <vector> #include <map> #include <set> #include <stack> #include <cmath> #include <cstdio> #include <algorithm> #include <iomanip> #define N 610*610*2+2 #define M 800100 #define LL __int64 #define inf 0x3f3f3f3f #define lson l,mid,ans<<1 #define rson mid+1,r,ans<<1|1 #define getMid (l+r)>>1 #define movel ans<<1 #define mover ans<<1|1 using namespace std; const LL mod = 1000000007; int head , mapp[610][610]; 4000 int n, m, cnt; struct node { int to; int cap;//剩余流量 int money;//费用 int next; }edge[M]; struct MCMF { int len ;//spfa求出的长度 int pre ;//spfa求出最短路径的前缀 int path ;//因为a->b可能有重复的边,所以记录是哪条边 bool vis ; void init() { memset(head, -1, sizeof(head)); cnt = 0; } void add(int u, int v, int cap, int money) { edge[cnt].to = v, edge[cnt].cap = cap, edge[cnt].next = head[u], edge[cnt].money = money, head[u] = cnt++; edge[cnt].to = u, edge[cnt].cap = 0, edge[cnt].next = head[v], edge[cnt].money = -money, head[v] = cnt++; } bool spfa(int s, int t) { memset(vis, false, sizeof(vis)); memset(pre, -1, sizeof(pre)); memset(path, -1, sizeof(path)); memset(len, -inf, sizeof(len)); queue<int> q; q.push(s); vis[s] = true; len[s] = 0; while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (len[v] < len[u] + edge[i].money&&edge[i].cap > 0) { len[v] = len[u] + edge[i].money; pre[v] = u; path[v] = i; if (!vis[v]) { vis[v] = true; q.push(v); } } } } return len[t] != -inf; } int MinCostMaxFlow(int s, int t) { LL sum = 0; while (spfa(s, t)) { int mmin = inf; for (int i = t; i != s && i != -1; i = pre[i]) { mmin = min(mmin, edge[path[i]].cap); } for (int i = t; i != s && i != -1; i = pre[i]) { edge[path[i]].cap -= mmin; edge[path[i] ^ 1].cap += mmin; } if (len[t] <= 0) { break; } sum += mmin*(len[t]); } return sum; } }; int main() { cin.sync_with_stdio(false); MCMF mcmf; int a, b, c, d; while (~scanf("%d",&n)) { mcmf.init(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { scanf("%d", &mapp[i][j]); if ((i == 0 && j == 0) || (i == n - 1 && j == n - 1)) { mcmf.add(i*n + j, i*n + j + n*n, 2, mapp[i][j]);//起点和终点可以走两次,点的费用为mapp[i][j](自身到自身)(当走完两边以后源点和汇点的容量都没有了所以就结束了) } else{ mcmf.add(i*n + j, i*n + j + n*n, 1, mapp[i][j]); } if (i < n - 1) { mcmf.add(i*n + j + n*n, (i + 1)*n + j, 1, 0);//从上到下 } if (j < n - 1) { mcmf.add(i*n + j + n*n, i*n + j + 1, 1, 0);//从左到右 } } } int s, t; s = 2 * n*n + 1;//源点 t = 2 * n*n + 2;//汇点 mcmf.add(s, 0, 2, 0);//起点和终点可以走两次 mcmf.add(2 * n*n - 1, t, 2, 0); printf("%d\n", mcmf.MinCostMaxFlow(s, t) - mapp[0][0] - mapp[n - 1][n - 1]); } return 0; }
HDU 3376
#include <iostream> #include <cstring> #include <string> #include <queue> #include <vector> #include <map> #include <set> #include <stack> #include <cmath> #include <cstdio> #include <algorithm> #include <iomanip> #define N 610*610*2+2 #define LL __int64 #define inf 0x3f3f3f3f #define lson l,mid,ans<<1 #define rson mid+1,r,ans<<1|1 #define getMid (l+r)>>1 #define movel ans<<1 #define mover ans<<1|1 using namespace std; const LL mod = 1000000007; int head , mapp[610][610]; int n, m, cnt; struct node { int to; int cap;//剩余流量 int money;//费用 int next; }edge[N << 2]; int len ;//spfa求出的长度 int pre ;//spfa求出最短路径的前缀 int path ;//因为a->b可能有重复的边,所以记录是哪条边 bool vis ; struct MCMF { void init() { memset(head, -1, sizeof(head)); cnt = 0; } void add(int u, int v, int cap, int money) { edge[cnt].to = v, edge[cnt].cap = cap, edge[cnt].next = head[u], edge[cnt].money = money, head[u] = cnt++; edge[cnt].to = u, edge[cnt].cap = 0, edge[cnt].next = head[v], edge[cnt].money = -money, head[v] = cnt++; } bool spfa(int s, int t) { memset(vis, false, sizeof(vis)); memset(pre, -1, sizeof(pre)); memset(path, -1, sizeof(path)); memset(len, -inf, sizeof(len)); queue<int> q; q.push(s); vis[s] = true; len[s] = 0; while (!q.empty()) { int u = q.front(); q.pop(); vis[u] = false; for (int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if (len[v] < len[u] + edge[i].money&&edge[i].cap > 0) { len[v] = len[u] + edge[i].money; pre[v] = u; path[v] = i; if (!vis[v]) { vis[v] = true; q.push(v); } } } } return len[t] != -inf; } int MinCostMaxFlow(int s, int t) { LL sum = 0; while (spfa(s, t)) { int mmin = inf; for (int i = t; i != s && i != -1; i = pre[i]) { mmin = min(mmin, edge[path[i]].cap); } for (int i = t; i != s && i != -1; i = pre[i]) { edge[path[i]].cap -= mmin; edge[path[i] ^ 1].cap += mmin; } if (len[t] <= 0) { break; } sum += mmin*len[t]; } return sum; } }; int main() { cin.sync_with_stdio(false); MCMF mcmf; int a, b, c, d; while (~scanf("%d",&n)) { mcmf.init(); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { scanf("%d", &mapp[i][j]); if ((i == 0 && j == 0) || (i == n - 1 && j == n - 1)) { mcmf.add(i*n + j, i*n + j + n*n, 2, mapp[i][j]);//起点和终点可以走两次,点的费用为mapp[i][j](自身到自身)(当走完两边以后源点和汇点的容量都没有了所以就结束了) } else{ mcmf.add(i*n + j, i*n + j + n*n, 1, mapp[i][j]); } if (i < n - 1) { mcmf.add(i*n + j + n*n, (i + 1)*n + j, 1, 0);//从上到下 } if (j < n - 1) { mcmf.add(i*n + j + n* c551 n, i*n + j + 1, 1, 0);//从左到右 } } } int s, t; s = 2 * n*n + 1;//源点 t = 2 * n*n + 2;//汇点 mcmf.add(s, 0, 2, 0);//起点和终点可以走两次 mcmf.add(2 * n*n - 1, t, 2, 0); printf("%d\n", mcmf.MinCostMaxFlow(s, t) - mapp[0][0] - mapp[n - 1][n - 1]); } return 0; }
相关文章推荐
- POJ 2135 Farm Tour && HDU 2686 Matrix && HDU 3376 Matrix Again 费用流求来回最短路
- hdu 2686 Matrix && hdu 3367 Matrix Again (最大费用最大流)
- POJ 2135 Farm Tour && HDU 2686 Matrix && HDU 3376 Matrix Again 费用流求来回最短路
- 【HDU 3376 Matrix Again】网络流 & 拆点 & 最大费用最大流
- HDU 3376 && 2686 方格取数 最大和 费用流裸题
- HDU 3376 && 2686 方格取数 最大和 费用流裸题
- HDU 2686 Matrix 3376 Matrix Again(费用流)
- hdu 3376 && hdu 2686 最大费用最大流
- HDU 2686 Matrix 3376 Matrix Again(费用流)
- HDU 3376--Matrix Again【最大费用最大流 && 经典建图】
- HDU 2686 Matrix||HDU 3376 Matrix Again (拆点费用流)
- hdu 3376 Matrix Again 最大费用流
- hdu 2686 Matrix【最大费用流】
- hdu 2686 Matrix hdu 3376 Matrix Again 费用流
- hdu 2686 Matrix hdu 3376 Matrix Again 费用流
- hdu 3376 Matrix Again【最大费用流】
- HDU 2686 Matrix(最大费用最大流+拆点)
- 【网络流】 HDOJ 2686 Matrix && HDOJ 3376 Matrix Again
- HPU 2686--Matrix【最大费用最大流 && 经典建图】
- hdu 2686 Matrix(最大费用流)