当前位置: 首页 > news >正文

P6954 [NEERC 2017] Connections 题解

P6954 [NEERC 2017] Connections 题解

题目链接

我的博客

前言

本篇总结:清空!

思路

因为删边之后还需要保证所有强连通关系不变,所以我们可以想到所有强连通分量之间的边一定可以删除。

接下来我们考虑如何删除保留一个强连通分量里面的边。

对于有向图来说,\(n\) 个结点强连通需要保证有不超过 \(2n\) 条边。

因此可以在一个强连通分量里面随意找一个点,对它跑一遍正图,一遍反图。(即跑内向树和外向树),保留所有树边。

最后如果删除的边还不满 \(2n\) 条,那么随便选没有被保留的边,直到满 \(2n\) 条边。

警示后人

多测一定要全部清空啊!!!包括 tarjan 的各种数组,最终的标记数组,以及存边的数组!

代码

const int N=1e5+10;
int T,n,m;
int out[N],tot;
//out:是(0)否(1)输出 i 边
//tot:保留的边的个数
struct edge{int nxt[N],to[N];int head[N],num_Edge=0;void add_Edge(int from,int t){nxt[++num_Edge]=head[from];to[num_Edge]=t;head[from]=num_Edge;}void clear(){//清空!for(int i=0;i<N-5;i++) head[i]=0;num_Edge=0;}
}e1,e2;
//e1:正向图,e2:反向图//tarjan板子
int dfn[N],low[N],dfscnt=0;
int scc[N],sc=0,st[N],top=0;
bool vis[N];
//以上的数组都需要清空!!!
void tarjan(int u){dfn[u]=low[u]=++dfscnt;st[++top]=u;vis[u]=1;for(int i=e1.head[u];i;i=e1.nxt[i]){int v=e1.to[i];if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(vis[v]){low[u]=min(low[u],dfn[v]);}}if(low[u]==dfn[u]){sc++;while(st[top]!=u&&top){scc[st[top]]=sc;vis[st[top]]=0;top--;}scc[st[top]]=sc;vis[st[top]]=0;top--;}
}
//内向树
void dfs1(int u){vis[u]=1;for(int i=e1.head[u];i;i=e1.nxt[i]){int v=e1.to[i];if(vis[v]) continue;if(scc[v]==scc[u]) {out[i]=1;dfs1(v);}} 
}
//外向树
void dfs2(int u){vis[u]=1;for(int i=e2.head[u];i;i=e2.nxt[i]){int v=e2.to[i];if(vis[v]) continue;if(scc[u]==scc[v]) {out[i]=1;dfs2(v);}}
}
void init(){e1.clear();e2.clear();for(int i=0;i<N-5;i++) out[i]=0;tot=0;	for(int i=1;i<=n;i++){dfn[i]=low[i]=0;scc[i]=0;}//尤其不要忘了这三个变量清空!sc=0;dfscnt=0;top=0;
}
void solve(){init();n=Read();m=Read();for(int i=1;i<=m;i++){int x=Read(),y=Read();e1.add_Edge(x,y);e2.add_Edge(y,x);}for(int i=0;i<N-5;i++) vis[i]=0;//每次用之前清空!!for(int i=1;i<=n;i++){if(!dfn[i]) tarjan(i);}for(int i=0;i<N-5;i++) vis[i]=0;for(int i=1;i<=n;i++){if(!vis[i]) dfs1(i);}for(int i=0;i<N-5;i++) vis[i]=0;for(int i=1;i<=n;i++){if(!vis[i]) dfs2(i);}for(int i=1;i<=m;i++) if(out[i]) tot++;for(int i=1;i<=m;i++){if(out[i]) continue;if(tot<2*n) out[i]=1,tot++;//如果不满 2n 条边}
//	puts("----");for(int i=1;i<=m;i++){if(out[i]) continue;printf("%d %d\n",e2.to[i],e1.to[i]);}
}
signed main(){T=Read();while(T--){solve();//多测函数好!}return 0; 
} 
http://www.jsqmd.com/news/34573/

相关文章:

  • 高级程序语言设计个人作业第四次
  • 什么是 Feed 流?
  • 调整 Halo2 Joe 主题友情链接页面样式
  • CF1463E Plan of Lectures
  • 基于单片机的元胞自动机仿真系统设计 - 详解
  • 251107
  • 2025年防水补漏企业TOP5:漏水维修、防水翻新、漏水检测
  • (鲜花)万宁五子棋 v0.2
  • ansible + docker compose, RustFS MNMD 架构的一键部署之道
  • 2025年海外仓服务最新推荐企业,欧洲海外仓、美国海外仓、亚马逊海外仓、TEMU海外仓、独立站海外仓服务商解析
  • 实用指南:RSA加密从原理到实践:Java后端与Vue前端全栈案例解析
  • Ubuntu 中创建全局可访问的共用目录
  • 开源 C++ QT QML 开发(十五)通讯--http下载 - 实践
  • 2025年11月不锈钢加工装饰制品优质厂家推荐榜:加工、屏风、栏杆等品类精选
  • P3978 概率论
  • 从iPhone转移到itel手机的联系人转移指南 - 实践
  • JT808,JT1078 —— AAC编码 —— 部标机语音对讲Java实现
  • DP 总结
  • 2025年11月7日
  • 【开题答辩全过程】以 爱运动健身小程序的设计与实现为例,包含答辩的障碍和答案
  • 高并发下如何保证 Caffeine + Redis 多级缓存的一致性问题?MySQL、Redis 缓存一致性问题? - 指南
  • 2025-11-07 PQ v.Next日志记录
  • [python刷题记录]-轮转数组-普通数组-中等
  • QT正在复兴?兰亭妙微带你看懂工业软件设计的新风口
  • 低代码如何真正降低企业数字化转型成本?
  • 低代码开发的核心流程
  • 字符串杂题
  • 低代码 vs 无代码:90% 的企业都分不清的核心差异
  • 轻言轻语
  • NIFI 使用HTTP 作为数据源接收数据