惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
Jina AI
Jina AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
P
Proofpoint News Feed
Last Week in AI
Last Week in AI
博客园 - 司徒正美
Martin Fowler
Martin Fowler
T
Tailwind CSS Blog
B
Blog RSS Feed
Vercel News
Vercel News
博客园 - 聂微东
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
M
MIT News - Artificial intelligence
Recent Announcements
Recent Announcements
GbyAI
GbyAI
L
LangChain Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Microsoft Security Blog
Microsoft Security Blog
C
Check Point Blog
MongoDB | Blog
MongoDB | Blog
B
Blog

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解
洛谷-P11942 [KTSC 2025] 重塑矩阵 题解
xiaoniu142857 · 2026-05-24 · via 博客园_首页

Solution

看到 \(01\) 矩阵,一个经典的转化是转化成二分图:建立 \(n\) 个行点 \(R_0 \sim R_{n-1}\)\(n\) 个列点 \(C_0 \sim C_{n-1}\)\(A_{i,j}\) 表示一条连接 \(R_i,C_j\) 的边。在此基础上可以想到两种建图方法:

Method 1

建无向图,\(A_{i,j}\) 作为边权。

不难发现原限制是 \(0/1\) 边各自的边导出子图为连通图的充分不必要条件。\(2n-1\) 条边恰好是一个生成树,但是发现生成树不好构造,我们就卡住了。

Method 2

建有向图,\(A_{i,j}\) 表示方向,转化成二分竞赛图:

  • \(A_{i,j}=1\):建边 \(R_i \to C_j\)
  • \(A_{i,j}=0\):建边 \(C_j \to R_i\)

那么原条件等价于原图中没有四元环。进一步地,可以归纳证明这样的二分图一定无环。即:二分竞赛图中,无四元环等价于整张图无环。

现在问题转化成了如何用 \(2n-1\) 条边表示这样一个有向无环二分图。我们只需要知道任意两点间的拓扑序大小关系。

注意到,若当前图中存在 \(k\) 个入度为 \(0\) 的点,在不取完这 \(k\) 个点之前,是不可能产生新的入度为 \(0\) 的点的。这样一层层剥掉入度为 \(0\) 的点,就将图分成了若干层。显然,同层内一定无边。那么我们只需要知道每个点所在的层。

显然,除第一层外,每个点必须有来自前一层的入边。对于每个点我们随便记录一条这样的边,会得到一个外向有向树森林,其中根为第一层的点,点在树中的深度就是它所在的层号。然后就做完了。

Code

#include "grid_encoding.h"
#include <vector>
#include <cstring>
#define rep(i,a,b) for(int i(a);i<b;++i)
#define rept(i,a,b) for(int i(a);i<=b;++i)
#define eb emplace_back
using namespace std;
namespace{
    const int N=1005;
    int n,in[N],d[N];
    vector<int> g[N],q;
}
void init(){
    memset(in,0,sizeof(in));
    memset(d,0,sizeof(d));
    rep(i,0,n*2) g[i].clear();
    q.clear(),q.reserve(n<<1);
}
void send(vector<vector<int>> A){
    n=A.size(),init();
    rep(i,0,n) rep(j,0,n){
        if(A[i][j]) g[i].eb(j+n),++in[j+n];
        else g[j+n].eb(i),++in[i];
    }
    rep(i,0,n*2) if(!in[i]) q.eb(i);
    while(!q.empty()){
        int u=q.back();
        q.pop_back();
        for(int v:g[u]){
            if(!--in[v]){
                q.eb(v);
                v>=n?select(u,v-n):select(v,u-n);
            }
        }
    }
}
vector<vector<int>> reconstruct(vector<vector<int>> B){
    n=B.size(),init();
    rep(i,0,n) rep(j,0,n){
        if(B[i][j]==1) g[i].eb(j+n),++in[j+n];
        else if(B[i][j]==0) g[j+n].eb(i),++in[i];
    }
    rep(i,0,n*2) if(!in[i]) q.eb(i);
    while(!q.empty()){
        int u=q.back();
        q.pop_back();
        for(int v:g[u]){
            if(!--in[v]){
                d[v]=d[u]+1;
                q.eb(v);
            }
        }
    }
    rep(i,0,n) rep(j,0,n){
        if(B[i][j]==-1) B[i][j]=d[i]<d[j+n];
    }
    return B;
}