cf22E(加最少的边形成强连通图)
题意:给出一个有向图,现在让你加最少的边让原图形成强连通图,并输出要加的边。
思路:这题很容易让人联想到缩点,因为题意的原因一定会存在回路,可是试想,缩点之后,可能有很多很多环,然后怎样去处理这么多入度出度都为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; }
持续更新博客地址:
blog.csdn.net/martinue