[题解] [TJOI2011] 构造矩阵
题面
题解
很容易看出来是道网络流的题目, 要是没有这个字典序最小, 直接建图跑一遍就好了, 考虑如何输出字典序最小的方案
我们可以贪心地去选择, 若当前点可以选0就选0, 不能选0就选1, 有一点像搜索, 但是直接搜索回溯肯定会爆炸, 考虑如何不回溯
用网络流优化, 若当前点选0后面有可行的方案, 直接选0, 若没有可行的方案, 这个点就只能选1了, 考虑到当前点的选择是在前面点已经选择完并确定有了可行解的情况下进行的, 所以这个策略是可行的, 至于时间复杂度的问题, 代码中会讲到
代码
###include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <queue>
#define itn int
#define reaD read
#define N 105
#define INF 1000000009
using namespace std;
int n, m, r[N], c[N], d[N << 1], S, T, head[N << 1], cur[N << 1], cnt = 1, id[N][N], ans[N][N];
struct edge { int to, next, flow; } e[20005];
inline int read()
{
int x = 0, w = 1; char c = getchar();
while(c < '0' || c > '9') { if (c == '-') w = -1; c = getchar(); }
while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
return x * w;
}
inline void add(int u, itn v, int w) { e[++cnt] = (edge) { v, head[u], w }; head[u] = cnt; e[++cnt] = (edge) { u, head[v], 0 }; head[v] = cnt; }
int bfs()
{
queue<int> q; memset(d, 0, sizeof(d));
q.push(S); d[S] = 1;
while(!q.empty())
{
int u = q.front(); q.pop();
for(int v, i = head[u]; i; i = e[i].next)
if(!d[v = e[i].to] && e[i].flow > 0) { d[v] = d[u] + 1; q.push(v); }
}
return d[T];
}
int dfs(int u, int a)
{
if(u == T || !a) return a;
int flow = 0;
for(int v, &i = cur[u]; i; i = e[i].next)
{
if(d[v = e[i].to] == d[u] + 1 && e[i].flow > 0)
{
int f = dfs(v, min(a, e[i].flow));
flow += f; a -= f; e[i].flow -= f; e[i ^ 1].flow += f;
}
if(!a) break;
}
if(a) d[u] = -1;
return flow;
}
int dinic() { int flow = 0; while(bfs()) { memcpy(cur, head, sizeof(head)); flow += dfs(S, INF); } return flow; }
bool check(itn x, int y)
{
dinic(); if(!r[x] || !c[y]) return 0; r[x]--; c[y]--;
//先考虑当前行或列是否已经选完了所有可选的0
if(e[id[x][y]].flow) { e[id[x][y]].flow = 0; return 1; }//若这条边flow = 1, 代表这条边没有被增广过, 也就是(x, y)这个点是0, 直接断掉这条边(保证以后增广不走他), return即可
else
{
/*若这条边flow = 0, 代表这条边被增广过, 这个点(x, y)当前为1, 考虑将他变成0是否有可行解,
由于这条边被增广过, 故必有一条S -> x -> y -> T的增广路, 手动退流, 再次增广, 若能找到一条新的增广路补上这条路断掉之后的影响, 代表点(x, y)可以为0, 否则, 不能为0, 将x -> y断掉, 表示强制走他, S -> x和y -> T这两条边的流量减1即可, 由于没有被增广过, 刚刚正向边加上后流量必然>0, 将正向边流量减1即可*/
e[id[x][y] ^ 1].flow = 0; e[id[x][m + 1] ^ 1].flow--; e[id[x][m + 1]].flow++;
e[id[n + 1][y] ^ 1].flow--; e[id[n + 1][y]].flow++; if(dinic() == 1) return 1;
r[x]++; c[y]++; e[id[n + 1][y]].flow--; e[id[x][m + 1]].flow--; return 0;
}
//由于每次断边后只需要找到一条新的增广路即可, 所以每次dinic只会找到一条增广路, 复杂度是正确的
}
int main()
{
n = read(); m = read(); S = n + m + 1; T = n + m + 2;
for(int i = 1; i <= n; i++) r[i] = read();
for(int i = 1; i <= m; i++) c[i] = read();
for(int i = 1; i <= n; i++)
{
id[i][m + 1] = cnt + 1; add(S, i, r[i]);
for(int j = 1; j <= m; j++)
{
if(i == 1) id[n + 1][j] = cnt + 1, add(j + n, T, c[j]);
id[i][j] = cnt + 1; add(i, j + n, 1);
}
}
for(int i = 1; i <= n; i++) r[i] = m - r[i];
for(int j = 1; j <= m; j++) c[j] = n - c[j];
for(int i = 1; i <= n; i++, puts(""))
for(int j = 1; j <= m; j++) printf("%d", check(i, j) ? 0 : 1);
return 0;
}
[题解] [TJOI2011] 构造矩阵的更多相关文章
- [TJOI2011]构造矩阵
考虑优化贪心,不回溯,对于每一位,你都判一下放0的话后面是否有解,用网络流判是否可以完美匹配就行了. 但这样时间复杂是错的,所以不必每次都重新建图,现在原来的图中看一下该行列是否已经匹配,若没有,则强 ...
- 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. ...
- Number Sequence(HDU 1005 构造矩阵 )
Number Sequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)T ...
- hdu 5015 233 Matrix(构造矩阵)
http://acm.hdu.edu.cn/showproblem.php?pid=5015 由于是个二维的递推式,当时没有想到能够这样构造矩阵.从列上看,当前这一列都是由前一列递推得到.依据这一点来 ...
- [数学-构造矩阵]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的公式!!! ...
- poj 3735 Training little cats(构造矩阵)
http://poj.org/problem?id=3735 大致题意: 有n仅仅猫,開始时每仅仅猫有花生0颗,现有一组操作,由以下三个中的k个操作组成: 1. g i 给i仅仅猫一颗花生米 2. e ...
- HDU 3306 Another kind of Fibonacci ---构造矩阵***
Another kind of Fibonacci Time Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- 构造矩阵解决这个问题 【nyoj299 Matrix Power Series】
矩阵的又一个新使用方法,构造矩阵进行高速幂. 比方拿 nyoj299 Matrix Power Series 来说 给出这样一个递推式: S = A + A2 + A3 + - + Ak. 让你求s. ...
- UVa 11149 Power of Matrix (矩阵快速幂,倍增法或构造矩阵)
题意:求A + A^2 + A^3 + ... + A^m. 析:主要是两种方式,第一种是倍增法,把A + A^2 + A^3 + ... + A^m,拆成两部分,一部分是(E + A^(m/2))( ...
随机推荐
- SQL Server中的锁可以分为如下几类
从大类来看,SQL Server中的锁可以分为如下几类: 共享锁(S锁):用于读取资源所加的锁.拥有共享锁的资源不能被修改.共享锁默认情况下是读取了资源马上被释放.比如我读100条数据,可以想像成读完 ...
- js判断是否是对象获取子窗体值
判断是否是对象 Object.prototype.toString.call(obj) 装换为数组 Array.prototype.slice.call(obj) 父窗体获取值子窗体值$(functi ...
- ES6入门一:块级作用域(let&const)、spread展开、rest收集
let声明 const声明 块级作用域 spread/rest 一.let声明与块作用域 在ES6之前,JavaScript中的作用域基本单元就是function.现在有了let就可以创建任意块的声明 ...
- npm 设置淘宝镜像
永久 npm config set registry https://registry.npm.taobao.org 直接安装 cnpm 替代 npm npm install -g cnpm --re ...
- SQL Server 2005 实现数据库同步备份 过程--结果---分析
数据库复制: 简单来说,数据库复制就是由两台服务器,主服务器和备份服务器,主服务器修改后,备份服务器自动修改. 复制的模式有两种:推送模式和请求模式,推送模式是主服务器修改后,自动发给备份服务器, ...
- EF 将MSSQL 更换成 POSTRESQL
前提概要:项目里已存在MSSQL 的 DB FIRST 的EDMX, 想将项目的数据库转换成 POSTGRESQL. 解决方法: 1,新建项目, 连接MSSQL 建立模型,用来源于数据库 CODE F ...
- 关于php的发展前景
php7 宣称速度比php5.6快两倍,宣称要打破一切旧规则 2015年,php 7.0发布 2016年,php 7.1发布 2017年,php 7.2发布 2018年,php 7.3发布 2019年 ...
- 电子工程师需要了解的SMT贴片质量问题汇总(转)
点胶工艺中常见的缺陷与解决方法 拉丝/拖尾 拉丝/拖尾是点胶中常见的缺陷,产生的原因常见有胶嘴内径太小.点胶压力太高.胶嘴离PCB的间距太大.贴片胶过期或品质不好.贴片胶粘度太好.从冰箱中取出后未能恢 ...
- 在RecyclerView中集成QQ汽泡一
上次已经实现了QQ汽泡的自定义View的效果[http://www.cnblogs.com/webor2006/p/7726174.html],接着再将它应用到列表当中,这样才算得上跟QQ的效果匹配, ...
- Ubuntu18.04系统执行语句时出现错误Failed to load module "canberra-gtk-module"
Ubuntu18.04系统执行gnuradio-companion时,命令行提示错误Failed to load module "canberra-gtk-module",虽然看起 ...