AtCoder292 E 思维

该问题探讨的是如何在给定的有向图中添加最少的边,以确保图变成强连通图。算法通过从每个顶点开始进行广度优先搜索,计算需要额外添加的边的数量。复杂度为O(n^2),其中n是顶点数量。

题意:

给定一副n(n≤3000)n(n\leq 3000)n(n3000)个顶点,mmm条有向边的图,可以在图中添加有向边,求添加的最少边数,使得这副图满足:如果顶点aaa到顶点bbb有边,顶点bbbccc右有边,那么顶点aaa到顶点ccc也有边

Solution:

考虑一条单向链,按指向的方向按顺序是A,B,C,D,...A,B,C,D,...A,B,C,D,...

显然,A→B,B→CA\rightarrow B,B\rightarrow CAB,BC需要添加一条边A→CA\rightarrow CAC,此时A→C,C→DA\rightarrow C,C\rightarrow DAC,CD需要添加A→DA\rightarrow DAD。更一般的情况是,在从AAA出发能到达的顶点里,只有与AAA距离为1的不需要添加边,只需要和其他点建边即可,并查集不适合有向图,O(n)O(n)O(n)的搜索可以满足要求,每个顶点搜索一次,总复杂度O(n2)O(n^2)O(n2)

#include<iostream>
#include<vector>
#include<cstdlib>
#include<numeric>
#include<unistd.h>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<set>
#include<map>
#include<stack>
#include<utility>
#include<cctype>
#include<cassert>
#include<thread>
#include<bitset>
using namespace std;
 
using ll=long long;
const int N=2e5+5,inf=0x3fffffff;
const long long INF=0x3fffffffffffffff,mod=998244353;
 
struct way {
	int to,next;
}edge[N<<1];
int cnt,head[N];
 
void add(int u,int v) {
	edge[++cnt].to=v;
	edge[cnt].next=head[u];
	head[u]=cnt;
}
 
int n,m,dis[N],vis[N];
 
int main() {
	#ifdef stdjudge
		freopen("in.txt","r",stdin);
		auto TimeFlagFirst=clock();
	#endif
 
	std::ios::sync_with_stdio(false);
	std::cin.tie(nullptr);
 
	cin>>n>>m;
	for(int i=1;i<=m;i++) {
		int u,v;
		cin>>u>>v;
		add(u,v);
	}
 
	int tot=0;
	queue<int>q;
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=n;j++) vis[j]=false;
		while(!q.empty()) q.pop();
		q.push(i);
 
		while(!q.empty()) {
			int u=q.front(); q.pop();
			vis[u]=true;
			for(int j=head[u];j;j=edge[j].next) {
				int v=edge[j].to;
				if(vis[v]) continue;
				q.push(v);
			}
		}
 
		for(int j=1;j<=n;j++) {
			if(i!=j&&vis[j]) tot++;
		}
		for(int j=head[i];j;j=edge[j].next) tot--;
	}
 
	cout<<tot<<endl;
 
	#ifdef stdjudge
		freopen("CON","r",stdin);
		std::cout<<std::endl<<"耗时:"<<std::clock()-TimeFlagFirst<<"ms"<<std::endl;
		std::cout<<std::flush;
		system("pause");
	#endif
    return 0;
}
### AtCoder编程题库概述 AtCoder是一个面向全球程序员的在线竞赛平台,提供多种难度级别的比赛和练习题目。对于希望提升算法能力的学习者来说,AtCoder提供了丰富的资源来满足不同层次的需求。 #### 初学者友好型赛事——Beginner Contest系列 针对初学者设计的比赛称为“Beginner Contest”,简称ABC[^1]。这类比赛通常包含若干道由易到难排列的任务,适合那些刚开始接触算法竞赛的人群参与并学习。每场比赛都会设置A至E/F等级别的挑战项目,其中: - A/B类问题较为基础,主要考察基本语法理解和简单逻辑思考; - C/D类则会涉及到一些常见的数据结构或经典算法的应用; - 而E/F级别往往需要更深入的理解以及创造性解决问题的能力[^2]。 #### 数学推理与组合数专题训练 除了常规赛外,还有专门围绕特定知识点展开的主题活动。例如,在一次比赛中出现了关于数学推理加组合数计算的问题(E级),这不仅考验选手们对离散数学概念掌握程度,同时也检验其能否灵活运用这些理论解决实际编码难题[^3]。 #### 进阶挑战——F级别高难度试题解析 随着技能水平提高,可以尝试更高难度的F级别题目。此类问题可能涉及复杂的数据处理技巧或是新颖独特的解法思路。通过研究过往优秀参赛者的解答案例(如ABCF205),能够帮助加深理解,并启发新的思维方式去应对更加棘手的技术挑战[^4]。 ```python # Python 示例代码用于求解某个具体问题(假设为斐波那契序列) def fibonacci(n): if n <= 0: return 0 elif n == 1: return 1 else: a, b = 0, 1 for _ in range(2, n + 1): a, b = b, a + b return b ``` 为了更好地利用AtCoder进行有效率地刷题练习,建议先从简单的Beginner Contest入手,逐步积累经验后再向更具挑战性的领域迈进。同时也要注重总结归纳常见模式和技术要点,这样才能不断提高自己的竞争力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值