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

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
爱范儿
爱范儿
H
Help Net Security
V
Visual Studio Blog
J
Java Code Geeks
Stack Overflow Blog
Stack Overflow Blog
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
MyScale Blog
MyScale Blog
The Cloudflare Blog
Martin Fowler
Martin Fowler
D
Docker
腾讯CDC
F
Fortinet All Blogs
雷峰网
雷峰网
GbyAI
GbyAI
G
Google Developers Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Recent Announcements
Recent Announcements
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Blog — PlanetScale
Blog — PlanetScale
Engineering at Meta
Engineering at Meta
博客园 - 聂微东
博客园 - 叶小钗

博客园_首页

Linux实操--组管理、权限管理和定时任务 Java + EasyExcel 实现单个接口导出多个Excel Mem0 源码解析系列(二):提示词工程的深度剖析 Openclaw TaskFlow究竟是什么?和普通Skill技能有什么区别 博文阅读密码验证 - 博客园 嘉立创开源:应该是全网MicroPython教程最多的开发板 Hermes Agent 集成实践:从协议到生产 2026年AI编程工具横评:Cursor、Codex、Claude Code、Zed、Windsurf Java程序员必看的RAG入门教程 2026 AI效率神器:Superpowers + Claude Code 保姆级教程 本地大模型部署全攻略:从 0 到 1 玩转 Ollama 【从0到1构建一个ClaudeAgent】内存管理-上下文压缩 .NET 高级开发 | 设计、实现一个事件总线框架 电子小白入门之NE555 3. WorkBuddy:隐藏玩法,一键召唤专家,让 AI 以"专家身份"给你干活 和AI一起搞事情#3:Claude Teammate 游戏开发翻车实录 【OpenClaw】通过 Nanobot 源码学习架构---(7)Memory C# .NET 周刊|2026年3月3期 我在 Debian 11 上把 K8s 单机搭起来了,过程没你想的那么顺(/opt 目录版) 深度学习进阶(七)Data-efficient Image Transformer CLI+Skill搭建浏览器AI自动化框架,告别一切重复枯燥任务 告别Token账单无底洞:OpenClaw本地部署,重塑企业数据主权的唯一解 FastAPI+Vue:文件分片上传+秒传+断点续传,这坑我帮你踩平了! SBTI 爆火后,我做了个程序员版的 CBTI。。已开源 + 附开发过程 多模态检索开始进入工程期:用 Sentence Transformers 搭建可落地的 Multimodal RAG 100多行代码实现一个最简单的Agent(用ReAct) Claude Code 通关手册(八):推荐 5 个 Hooks,代码质量提升 3 倍 老板:“有人截图了!”。安全部门:“收到,马上查暗水印!” - why技术 技术之外,皆是人间 C#/.NET/.NET Core技术前沿周刊 | 第 69 期(2026年4.01-4.12)
洛谷-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;
}