题意:给出一个有向图,现在让你加最少的边让原图形成强连通图,并输出要加的边。
思路:这题很容易让人联想到缩点,因为题意的原因一定会存在回路,可是试想,缩点之后,可能有很多很多环,然后怎样去处理这么多入度出度都为0的缩点?而且这些缩点是要按照顺序去连接的,否则肯定无法强连通,不仅是这些环,还有不是环的缩点,缩完点之后的处理反而变的很是复杂。所以这题的思路得换!因为这一题一题的原因,我们可以直接dfs去搜索入度为0的点最终的尾巴,还有就是环自身就相当于一个入度为0的点,也得dfs,搜索完了之后我们可以得到很多链式的起点和终点,然后我们要做的就是把这些链按照顺序首尾相连就ok!
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
int next[100010],rd[100010];
int vis[100010];
int dfs(int x)
{
vis[x]=1;
if(!vis[next[x]])
return vis[x]=dfs(next[x]);
else return vis[x]=x;
}
vector<int>head,tail;
int main ()
{
memset(vis,0,sizeof(vis));
int n;
scanf("%d",&n);
for(int i=1; i<=n; i++)
{
scanf("%d",&next[i]);
rd[next[i]]++;
}
int k=0;
for(int i=1; i<=n; i++)
if(!rd[i])
{
k++;
head.push_back(i);
tail.push_back(dfs(i));
}
int kk=k;
for(int i=1; i<=n; i++)
if(!vis[i])
{
k++;
head.push_back(i);
tail.push_back(dfs(i));
}
if(k==1&&!kk)
k=0;
printf("%d\n",k);
for(int i=0; i<k; i++)
printf("%d %d\n",tail[i],head[(i+1)%k]);///一条条处理出来的链首尾相连,最终强连通!
return 0;
}