Main Topic
Gives N (2<=n<=105) points, starting from each point you are connected to a point V (a total of n edges)
Now requires adding the fewest edges so the entire graph is a strong connected graph
Approach Analysis
This problem must not generalize: first of all the strong connected components and then the graph into a DAG (we can easily get the number of edges to add, but add which edges will become very troublesome)
Note One detail: The out of each point must be 1
What are the characteristics?
Starting from a point U DFS iterates through all the points that can be traversed, and at the end of the DFS you must get a ring! Also, because the out of each point is 1, all the points that are traversed can only form a ring! And this ring is still at the end of the path, if this is shrunk to a point, then we have to wait for a "inverted long" tree (there are only nodes from the leaf node to the root of the node, the ring is shrunk to the root)
As shown in the following figure:
We take all the points as starting point DFS once again will get a series of this diagram, of course, there is a special case: Ring! To make it easier to tell, we call them "chunking."
Define a starting point and end point for each, and then follow the line below:
When the entire graph has only one ring, it is impossible to add edges to make it a strong connected graph!
Link adjacent two tiles (the end of block A is connected to the beginning of block B)
Create a reverse edge for points that are not the starting point in the block with a 0 entry
Well, after adding the edges, the entire graph becomes a strong connected graph with the smallest number of plus edges.
At first I found a strong connectivity component, and then find out the degree of 0, into the degree of 0, and the degree of access is 0 of the contraction point, but only over 15 groups of data, and then changed to just over 10 sets of data, do not know where the problem, I hope the great God can point out, my error code:
#include <iostream> #include <stdio.h> #include <string> #include <string.h> #include < Vector>const int maxn=200200,maxm=500400;using namespace std;struct edge{int x,y,next;} e[maxm];int num[maxn];///each Connected component contains the number of points int dfn[maxn],low[maxn],v[maxn],s[maxn],b[maxn],h[maxn];int tot=0,cnt=0,times,t;int n,m;void init () {tot=0 ; memset (h,0,sizeof (h)); void Add (int x,int y) {e[++tot].x=x; E[tot].y=y; E[TOT].NEXT=H[X]; H[x]=tot;} int max (int a,int b) {if (a>b) return A; return b;} int min (int a,int b) {if (a>b) return B; return A;} void Tarjan (int x) {int y,i; times++; t++; Dfn[x]=low[x]=times; V[x]=1; S[t]=x; for (i=h[x]; i; i=e[i].next) {y=e[i].y; if (v[y]==0) {Tarjan (y); Low[x]=min (Low[x],low[y]); } if (v[y]==1) low[x]=min (Low[x],dfn[y]); } if (Dfn[x]==low[x]) {cnt++; do {y=s[t--]; b[y]=cnt;///belongs to which strong connected component, CNT is also the number of strongly connected components 1-cnt v[y]=2; num[cnt]++; } while (y!=x); }}void solve (int n) {times=0; t=0; cnt=0; memset (dfn,0,sizeof (DFN)); memset (num,0,sizeof (num)); memset (v,0,sizeof (v)); for (int i=1; i<=n; i++) if (!dfn[i]) Tarjan (i);} int In[maxn],out[maxn];int Uin[maxn],uout[maxn],uiu[maxn];vector<int>hd[maxn];int Main () {int t; scanf ("%d", &t); Init (); for (int i=1; i<=t; i++) {int u; scanf ("%d", &u); Add (I,u); } solve (t); if (cnt==1) {puts ("0"); return 0; } memset (In,0,sizeof (in)); Memset (out,0,sizeof (out)); memset (uin,0,sizeof (Uin)); memset (uout,0,sizeof (uout)); memset (uiu,0,sizeof (Uiu)); for (int i=1, i<=t; i++) {for (int j=h[i]; j!=0; j=e[j].next) {int y=e[j].y; Hd[b[i]].push_back (i); Hd[b[y]].push_back (y); if (B[i]==b[y]) continue; out[b[i]]++; in[b[y]]++; }} int k=0,k2=0,k1=0; for (int i=1; i<=cnt; i++) {if (in[i]==0&&out[i]==0) {uiu[k++]=i; } else {if (in[i]==0) uin[k1++]=i; if (out[i]==0) uout[k2++]=i; }} if (K1>K2) {printf ("%d\n", k1+k*2); for (int i=0; i<k2; i++) printf ("%d%d\n", hd[uout[i]][0],hd[uin[i]][0]); for (int i=k2; i<k1; i++) printf ("%d%d\n", hd[uout[0]][0],hd[uin[i]][0]); for (int i=0; i<k; i++) {printf ("%d%d\n", hd[uin[0]][0],hd[uiu[i]][0]); printf ("%d%d\n", hd[uiu[i]][0],hd[uin[0]][0]); }} else {printf ("%d\n", k2+k*2); for (int i=0; i<k1; i++) printf ("%d%d\n", hd[uout[i]][0],hd[uin[i]][0]); for (int i=k1; i<k2; i++) printf ("%d%d\n", hd[uout[i]][0],hd[uin[0]][0]); if (k2!=0) {for (int i=0; i<k; i++) {printf ("%d%d\n", hd[uout[0]][0],hd[uiu[i]][0]); printf ("%d%d\n", hd[uiu[i]][0],hd[uout[0]][0]); }} else {for (int i=0; i<k-1; i++) {printf ("%d%d\n", Hd[uiu [I]] [0],hd[uiu[i+1]][0]); printf ("%d%d\n", hd[uiu[i+1]][0],hd[uiu[i]][0]); }}} return 0;}AC code, very short, to learn the code of seniors:
#include <iostream> #include <vector> #include <stdio.h> #include <string.h>using namespace std ; const int Maxn=200020;int in[maxn],scl[maxn];vector <int>e[maxn];vector<int>In;vector<int>Out; int dfs (int u) {scl[u]=1; int v=e[u][0]; if (!scl[v]) return Scl[u]=dfs (v); else return scl[u]=u;} int main () {int n,k,t; while (~SCANF ("%d", &n)) {memset (in,0,sizeof (in)); for (int i=1;i<=n;i++) {int u; scanf ("%d", &u); E[i].push_back (U); in[u]++; } k=0; memset (scl,0,sizeof (SCL)); for (int i=1;i<=n;i++) {if (!in[i]) {k++; In.push_back (i); Out.push_back (Dfs (i)); }} t=k; for (int i=1;i<=n;i++) {if (!scl[i]) {k++; In.push_back (i); Out.push_back (Dfs (i));}} if (k==1&&t==0) k=0; printf ("%d\n", K); for (int i=0;i<k;i++) printf ("%d%d\n", out[i],in[(i+1)%k]); }//cout << "Hello world!" << Endl; return 0;}
Codeforce 22#div2e