题意:

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

思路:

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

目就是不但要求满流,某些点还有上限制,或者下限制,那么就直接是上下流呗,对了还有一个地方提醒一下,在建图之前判断一下有没有输入数据冲突的情况,下面说关键部分,也就是建图,建图之前定义几个变量,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 学习阶段性感想

    阶段性感想·操千曲而后晓声 回顾 从2月17日 到 今天 4月19日,我算是暂时完成了Java入门的学习了. 从基本语法到面向对象,从常见API到字符串集合,从文件处理到多线程,我学到了很多,很多很多 ...

  2. Java 集合框架 03

    集合框架·HashSet 和 TreeSet HashSet存储字符串并遍历 * A:Set集合概述及特点 * 通过API查看即可 * 无索引,不可以重复,无序 * B:案例演示 * HashSet存 ...

  3. OpenCV 之 角点检测

    角点 (corners) 的定义有两个版本:一是 两条边缘的交点,二是 邻域内具有两个主方向的特征点. 一般而言,角点是边缘曲线上曲率为极大值的点,或者 图像亮度发生剧烈变化的点.例如,从人眼角度来看 ...

  4. cocos 向左滚动公告

      properties:{ lblNotice:[cc.Node], speed:1, curtext:null }, start (){ this.getNotice(); }, getNotic ...

  5. 如何使用Typora写博客

    如何写博客及Typora的使用 Typora Typora是写好博客的一个重要的软件,下面我们来介绍如何安装以及使用它 安装 官网下载Typora 较慢,首先附上Typora安装包: 链接:https ...

  6. C++11正则表达式

  7. Nacos 2.0 正式发布,性能提升 10 倍!!

    3月20号,Nacos 2.0.0 正式发布了! Nacos 简介: 一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台. 通俗点讲,Nacos 就是一把微服务双刃剑:注册中心 + 配置中 ...

  8. PAT (Advanced Level) Practice 1027 Colors in Mars (20 分) 凌宸1642

    PAT (Advanced Level) Practice 1027 Colors in Mars (20 分) 凌宸1642 题目描述: People in Mars represent the c ...

  9. Python异步asyncio快速实践模版

    只是参考快速跑起来模版,细节或者封装流畅使用需要详细阅读aiohttp文档 1 import asyncio 2 3 async def foo(): 4 await print('bar') 5 6 ...

  10. C++并发与多线程学习笔记--基本概念和实现

    基本概念 并发 可执行程序.进程.线程 学习心得 并发的实现方法 多进程并发 多线程并发 总结 C++标准库 基本概念 (并发.进程.线程)区分C++初级编程和中高级编程 并发 两个或者更多的任务同时 ...