题意:
给定一副n(n≤3000)n(n\leq 3000)n(n≤3000)个顶点,mmm条有向边的图,可以在图中添加有向边,求添加的最少边数,使得这副图满足:如果顶点aaa到顶点bbb有边,顶点bbb到ccc右有边,那么顶点aaa到顶点ccc也有边
Solution:
考虑一条单向链,按指向的方向按顺序是A,B,C,D,...A,B,C,D,...A,B,C,D,...
显然,A→B,B→CA\rightarrow B,B\rightarrow CA→B,B→C需要添加一条边A→CA\rightarrow CA→C,此时A→C,C→DA\rightarrow C,C\rightarrow DA→C,C→D需要添加A→DA\rightarrow DA→D。更一般的情况是,在从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;
}
该问题探讨的是如何在给定的有向图中添加最少的边,以确保图变成强连通图。算法通过从每个顶点开始进行广度优先搜索,计算需要额外添加的边的数量。复杂度为O(n^2),其中n是顶点数量。
363

被折叠的 条评论
为什么被折叠?



