POJ 2396 构造矩阵(上下流)
来源:互联网 发布:深圳众诚网络 编辑:程序博客网 时间:2024/06/05 18:34
题意:
要求构造一个矩阵,给你行和,列和,还有一些点的上下范围,输出一个满足题意的矩阵。
思路:
这个题目很经典,这是自己看上下流后接触的第一道题,感觉很基础的一道题目,现在我们来分析下,如果这个题目是只给行和,列和,让我们构造矩阵应该很简单了,直接一遍最大流,然后判断是否满流,满流就把残余网络拿出来,整理下就是答案了,关键这个题
所有的列j连接终点t add(j ,t ,列和 ,列和);
建立一条t -> s add(t ,s ,0 ,INF);//为了把有源汇的最大流变成无源的
对于任意两点i,j add(i ,j ,下限 ,上限);
简单说下上下界网络流可行流判断
首先,可行流的判断就是根据在流里面,任意点的流入和流出永远都必须是相等的。
对于一个加边操作,a -> b ,下界 上界 可以这样处理
a -> b 流量为上界减去下界 这个可以叫自由边(就是不是必须流的边)
a -> tt ,ss -> b 流量都是下界 这两个叫做必须边,要想有解,必须边最后必须满流
如果是有源的,那么我们就 add(t ,s ,0 ,INF);变成无源
要求构造一个矩阵,给你行和,列和,还有一些点的上下范围,输出一个满足题意的矩阵。
思路:
这个题目很经典,这是自己看上下流后接触的第一道题,感觉很基础的一道题目,现在我们来分析下,如果这个题目是只给行和,列和,让我们构造矩阵应该很简单了,直接一遍最大流,然后判断是否满流,满流就把残余网络拿出来,整理下就是答案了,关键这个题
目就是不但要求满流,某些点还有上限制,或者下限制,那么就直接是上下流呗,对了还有一个地方提醒一下,在建图之前判断一下有没有输入数据冲突的情况,下面说关键部分,也就是建图,建图之前定义几个变量,s(源点),t(汇点),ss(超级源点),tt(超级汇点).
所有的列j连接终点t add(j ,t ,列和 ,列和);
建立一条t -> s add(t ,s ,0 ,INF);//为了把有源汇的最大流变成无源的
对于任意两点i,j add(i ,j ,下限 ,上限);
简单说下上下界网络流可行流判断
首先,可行流的判断就是根据在流里面,任意点的流入和流出永远都必须是相等的。
对于一个加边操作,a -> b ,下界 上界 可以这样处理
a -> b 流量为上界减去下界 这个可以叫自由边(就是不是必须流的边)
a -> tt ,ss -> b 流量都是下界 这两个叫做必须边,要想有解,必须边最后必须满流
如果是有源的,那么我们就 add(t ,s ,0 ,INF);变成无源
最后跑一遍 ss,tt的最大流,如果满流则有可行解,输出答案的话知道把所有自由边拿出来,加上下限就可以了。(因为此时下限已满流).
#include<stdio.h>#include<string.h>#include<queue>#define N_node 240#define N_edge 50000#define INF 1000000000using namespace std;typedef struct{ int from ,to ,next ,cost;}STAR;typedef struct{ int x ,t;}DEP;STAR E[N_edge];DEP xin ,tou;int list[N_node] ,listt[N_node] ,tot;int deep[N_node] ,sum_must;int map[220][22][3];int Ans[220][22];int maxx(int x ,int y){ return x > y ? x : y;}int minn(int x ,int y){ return x < y ? x : y;}void add(int a ,int b ,int c){ E[++tot].from = a; E[tot].to = b; E[tot].cost = c; E[tot].next = list[a]; list[a] = tot; E[++tot].from = b; E[tot].to = a; E[tot].cost = 0; E[tot].next = list[b]; list[b] = tot;}void ADD(int a ,int b ,int c ,int d ,int ss ,int tt){ add(a ,b ,d - c); add(a ,tt ,c); add(ss ,b ,c); sum_must += c;}bool BFS_Deep(int s ,int t ,int n){ xin.x = s ,xin.t = 0; queue<DEP>q; q.push(xin); memset(deep ,255 ,sizeof(deep)); deep[s] = 0; while(!q.empty()) { tou = q.front(); q.pop(); for(int k = list[tou.x] ;k ;k = E[k].next) { xin.x = E[k].to; xin.t = tou.t + 1; if(deep[xin.x] != -1 || !E[k].cost) continue; deep[xin.x] = xin.t; q.push(xin); } } for(int i = 0 ;i <= n ;i ++) listt[i] = list[i]; return deep[t] != -1;}int DFS_Flow(int s ,int t ,int flow){ if(s == t) return flow; int nowflow = 0; for(int k = listt[s] ;k ;k = E[k].next) { listt[s] = k; int to = E[k].to; int c = E[k].cost; if(deep[to] != deep[s] + 1 || !c) continue; int tmp = DFS_Flow(to ,t ,minn(c ,flow - nowflow)); nowflow += tmp; E[k].cost -= tmp; E[k^1].cost += tmp; if(nowflow == flow) break; } if(!nowflow) deep[s] = 0; return nowflow;}int DINIC(int s ,int t ,int n){ int ans = 0; while(BFS_Deep(s ,t ,n)) { ans += DFS_Flow(s ,t ,INF); } return ans;}bool jude(int n ,int m){ for(int i = 1 ;i <= n ;i ++) for(int j = 1 ;j <= m ;j ++) if(map[i][j][1] > map[i][j][2]) return 0; return 1;}int main (){ int a ,b ,c ,i ,j ,n ,m ,w ,T; char str[4]; scanf("%d" ,&T); while(T--) { scanf("%d %d" ,&n ,&m); memset(list ,0 ,sizeof(list)) ,tot = 1; sum_must = 0; int s = 0 ,t = n + m + 1 ,ss = n + m + 2 ,tt = n + m + 3; for(i = 1 ;i <= n ;i ++) { scanf("%d" ,&a); ADD(s ,i ,a ,a ,ss ,tt); } for(i = 1 ;i <= m ;i ++) { scanf("%d" ,&a); ADD(i + n ,t ,a ,a ,ss ,tt); } for(i = 1 ;i <= n ;i ++) for(j = 1 ;j <= m ;j ++) map[i][j][1] = 0 ,map[i][j][2] = INF; scanf("%d" ,&w); while(w--) { scanf("%d %d %s %d" ,&a ,&b ,str ,&c); if(a && b) { if(str[0] == '<') map[a][b][2] = minn(map[a][b][2] ,c - 1); if(str[0] == '=') map[a][b][1] = maxx(map[a][b][1] ,c) ,map[a][b][2] = minn(map[a][b][2] ,c); if(str[0] == '>') map[a][b][1] = maxx(map[a][b][1] ,c + 1); } if(a && !b) { for(j = 1 ;j <= m ;j ++) { if(str[0] == '<') map[a][j][2] = minn(map[a][j][2] ,c - 1); if(str[0] == '=') map[a][j][1] = maxx(map[a][j][1] ,c) ,map[a][j][2] = minn(map[a][j][2] ,c); if(str[0] == '>') map[a][j][1] = maxx(map[a][j][1] ,c + 1); } } if(!a && b) { for(j = 1 ;j <= n ;j ++) { if(str[0] == '<') map[j][b][2] = minn(map[j][b][2] ,c - 1); if(str[0] == '=') map[j][b][1] = maxx(map[j][b][1] ,c) ,map[j][b][2] = minn(map[j][b][2] ,c); if(str[0] == '>') map[j][b][1] = maxx(map[j][b][1] ,c + 1); } } if(!a && !b) { for(i = 1 ;i <= n ;i ++) for(j = 1 ;j <= m ;j ++) { if(str[0] == '<') map[i][j][2] = minn(map[i][j][2] ,c - 1); if(str[0] == '=') map[i][j][1] = maxx(map[i][j][1] ,c) ,map[i][j][2] = minn(map[i][j][2] ,c); if(str[0] == '>') map[i][j][1] = maxx(map[i][j][1] ,c + 1); } } } if(!jude(n ,m)) { puts("IMPOSSIBLE"); continue; } for(i = 1 ;i <= n ;i ++) for(j = 1 ;j <= m ;j ++) ADD(i ,j + n ,map[i][j][1] ,map[i][j][2] ,ss ,tt); ADD(t ,s ,0 ,INF ,ss ,tt); int Flow = DINIC(ss ,tt ,tt); if(Flow != sum_must) { puts("IMPOSSIBLE"); continue; } for(i = 2 ;i <= tot ;i ++) if(E[i].from >= 1 && E[i].from <= n && E[i].to >= n + 1 && E[i].to <= n + m) Ans[E[i].from][E[i].to - n] = E[i^1].cost + map[E[i].from][E[i].to - n][1]; for(i = 1 ;i <= n ;i ++) for(j = 1 ;j <= m ;j ++) if(j == m)printf("%d\n" ,Ans[i][j]); else printf("%d " ,Ans[i][j]); if(T) puts(""); } return 0;}
0 0
- POJ 2396 构造矩阵(上下流)
- POJ 3735 构造矩阵乘法
- POJ 3420 构造矩阵乘法
- POJ-3735 线性变换构造矩阵
- POJ 1977 构造矩阵乘法
- poj 3735 Training little cats(构造矩阵)
- poj 3735 Training little cats(构造矩阵)
- poj 3735 Training little cats(矩阵构造,快速幂)
- poj 3734 Blocks(构造矩阵加快速幂)
- POJ 3233 Matrix Power Series 解题报告(子矩阵构造+矩阵快速幂)
- [POJ 3735] Training little cats (构造矩阵、矩阵快速幂)
- POJ 3233 Matrix Power Series(构造矩阵加矩阵快速幂)
- hdu 3157 poj 3801 Crazy Circuits(有源汇有上下界最下流)
- poj 3070 Fibonacci (矩阵构造,水)
- poj 3233 Matrix Power Series (构造矩阵)
- poj-3233 Matrix Power(构造矩阵+矩阵快速幂)
- POJ 3735 E - Training little cats POJ - 3735 矩阵构造
- HDU5950Recursive sequence(构造矩阵+矩阵乘法)
- 读取本地文件存放list集合中
- D3D 纹理 例子程序
- 最长回文子串
- 集合框架(二)--Map集合
- nyoj1038纸牌游戏
- POJ 2396 构造矩阵(上下流)
- xls格式的文件导入
- STL算法分类记忆
- Overview of new gui¶
- 网络流入门 最大流,带下界,最小费用,EK算法,Dinic算法 模板
- Crane(线段树)
- Gartner Identifies China's Top 10 Strategic Technology Trends in 2014
- js replace
- 两个栈实现队列的功能