题意:

      要求构造一个矩阵,给你行和,列和,还有一些点的上下范围,输出一个满足题意的矩阵。

思路:

      这个题目很经典,这是自己看上下流后接触的第一道题,感觉很基础的一道题目,现在我们来分析下,如果这个题目是只给行和,列和,让我们构造矩阵应该很简单了,直接一遍最大流,然后判断是否满流,满流就把残余网络拿出来,整理下就是答案了,关键这个题

目就是不但要求满流,某些点还有上限制,或者下限制,那么就直接是上下流呗,对了还有一个地方提醒一下,在建图之前判断一下有没有输入数据冲突的情况,下面说关键部分,也就是建图,建图之前定义几个变量,s(源点),t(汇点),ss(超级源点),tt(超级汇点).


s连接所有的行i              add(s ,i ,行和 , 行和);

所有的列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 1000000000 using 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;
}

POJ 2396 构造矩阵(上下流)的更多相关文章

  1. POJ 2396 Budget 有上下界的网络流

    POJ 2396  Budget 题意简述:给定矩阵(每个元素都是非负整数)各行各列的和,并且限制其中的某些元素,给出一个可行解,特殊评测.矩阵规模小于200*20. 网络流的模型是显而易见的,不过对 ...

  2. POJ 2396 Budget ——有上下界的网络流

    给定矩阵的每行每列的和,和一些大于小于等于的限制.然后需要求出一组可行解. 上下界网络流. 大概的思想就是计算出每一个点他需要强行流入或者流出的量,然后建出超级源点和汇点,然后删除下界,就可以判断是否 ...

  3. poj 2396 Budget 边容量有上下界的最大流

    题意: 给一个矩阵的每行和及每列和,在给一些行列或点的限制条件.求一个满足的矩阵. 分析: 转化为有上下界的网络流,注意等于也是一种上下界关系,然后用dinic算法. 代码: //poj 2396 / ...

  4. poj 3735 Training little cats(构造矩阵)

    http://poj.org/problem?id=3735 大致题意: 有n仅仅猫,開始时每仅仅猫有花生0颗,现有一组操作,由以下三个中的k个操作组成: 1. g i 给i仅仅猫一颗花生米 2. e ...

  5. POJ 3233 Matrix Power Series(构造矩阵求等比)

    Description Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + … + Ak. ...

  6. POJ 3070 Fibonacci(矩阵高速功率)

    职务地址:POJ 3070 用这个题学会了用矩阵高速幂来高速求斐波那契数. 依据上个公式可知,第1行第2列和第2行第1列的数都是第n个斐波那契数.所以构造矩阵.求高速幂就可以. 代码例如以下: #in ...

  7. hdu 5015 233 Matrix(构造矩阵)

    http://acm.hdu.edu.cn/showproblem.php?pid=5015 由于是个二维的递推式,当时没有想到能够这样构造矩阵.从列上看,当前这一列都是由前一列递推得到.依据这一点来 ...

  8. [数学-构造矩阵]NEFU 1113

    依据题意.我已经推导出tn的公式.ti=ti.a+ti.b,ti.a=5*t(i-1).a+4*t(i-1).b,ti.b=t(i-1).a+t(i-1).b 然而以下居然不能继续推到sn的公式!!! ...

  9. HDU1757-A Simple Math Problem,矩阵快速幂,构造矩阵水过

    A Simple Math Problem 一个矩阵快速幂水题,关键在于如何构造矩阵.做过一些很裸的矩阵快速幂,比如斐波那契的变形,这个题就类似那种构造.比赛的时候手残把矩阵相乘的一个j写成了i,调试 ...

随机推荐

  1. Java垃圾回收机制详解

    前言 Java 相比 C/C++ 最显著的特点便是引入了自动垃圾回收 (下文统一用 GC 指代自动垃圾回收),它解决了 C/C++ 最令人头疼的内存管理问题,让程序员专注于程序本身,不用关心内存回收这 ...

  2. jwt以及如何使用jwt实现登录

    目录 jwt的使用和使用jwt进行登录 什么是jwt jwt的组成 为什么选择jwt session的缺点 jwt的优点 一个jwt的工具类 将jwt和登录进行结合 axios方式将jwt放在head ...

  3. webpack核心模块tapable用法解析

    前不久写了一篇webpack基本原理和AST用法的文章,本来想接着写webpack plugin的原理的,但是发现webpack plugin高度依赖tapable这个库,不清楚tapable而直接去 ...

  4. ASP.NET Core与Redis搭建一个简易分布式缓存

    ​本文主要介绍了缓存的概念,以及如何在服务器内存中存储内容.今天的目标是利用IDistributedCache来做一些分布式缓存,这样我们就可以横向扩展我们的web应用程序. 在本教程中,我将使用Re ...

  5. 谜题(JAVA语言)

    package 第三章习题; /*  * 有一个5*5的网络,其中恰好有一个格子是空的,其他格子各有一个字母.  * 一个有4种指令:A, B, L, R, 分别表示把空格上.下.左.右的相邻字母移到 ...

  6. 060_Cookie/Session

    目录 会话 有状态会话 保存会话的两种技术 cookie session 常见场景 Cookie cookie细节 删除cookie Session 什么是session session使用场景 se ...

  7. 7、MyBatis教程之分页实现

    8.分页实现 1.limit实现分页 思考:为什么需要分页? 在学习mybatis等持久层框架的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进行查询操作,如果查询大量数据的时候,我们往往使 ...

  8. (二)SpringBoot启动过程的分析-环境信息准备

    -- 以下内容均基于2.1.8.RELEASE版本 由上一篇SpringBoot基本启动过程的分析可以发现在run方法内部启动SpringBoot应用时采用多个步骤来实现,本文记录启动的第二个环节:环 ...

  9. 一文彻底搞懂JS前端5大模块化规范及其区别

    码文不易,转载请带上本文链接,感谢~ https://www.cnblogs.com/echoyya/p/14577243.html 目录 码文不易,转载请带上本文链接,感谢~ https://www ...

  10. 死磕Spring之AOP篇 - Spring AOP常见面试题

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读. Spring 版本:5.1 ...