Do question notes graph traversal P3916 ++

Today brush after meals questions, suddenly saw his task lists which have such a problem, it is intended to open write.

Said surface there is a problem to traverse the graph (n <= 10 ^ 5, m <= 10 ^ 5), it is natural to think of dfs, FIG using vector memory, I thought dfs two methods:

All points were dfs · For each point, each time dfs traversal can be achieved, and the maximum value
is very violent, the method is very simple, but the problem is that the worst case for each point needs to traverse the whole map, time complexity it is O (nm)
· largest first to point dfs, for each traverse point, if you can not put this point to the maximum of it.
This method has a very large relative to the optimization for a, the value of A is circulated from 1 to N, each access point i to node i are, each access point of time, the value of A is the most excellent, because then if we have access to the junction then the answer is certainly not the current big. The time complexity of this method is O (n + m) (bar)
code implementation:

#include <cstdio>
#include <cctype>
#include <vector>
#define MAXN 100010
#define _for(i,a,b) for (int i = a;i <= b;i++)
#define _fd(i,a,b) for (int i = b;i >= a;i--)
using namespace std;
vector <int> G[MAXN];
int n,m,a[MAXN];

inline int read() {
    int a = 0,f = 1;
    char v= getchar();
    while (!isdigit(v)) {
        if (v == '-') {
            f = -1;
        }
        v = getchar();
    }
    while (isdigit(v)) {
        a = a * 10 + v - 48;
        v = getchar();
    }
    return a * f;
}

inline void addedge(int u,int v) {
    G[v].push_back(u);
}

void dfs(int x,int p) {
    if (a[x]) {
        return ;
    }
    a[x] = p;
    int vv = G[x].size();
    for (int i = 0;i < vv;i++) {
        dfs(G[x][i],p);
    }
}

int main() {
    n = read(),m = read();
    _for(i,1,m) {
        int u = read(),v = read();
        addedge(u,v);
    }
    _fd(i,1,n) {
        dfs(i,i);
    }
    _for(i,1,n) {
        printf("%d ",a[i]);
    }
    return 0;
}

Later, when I look at a solution to a problem, suddenly found Tarjan also can answer!

Tarjan obtained using Unicom component, the answer point of each component inside China Unicom are the same!

Code implementation (problem solution):

#include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 
 7 const int maxn = 10e5 + 5;
 8 
 9 struct Edge{
10     int to,next;
11 }e[maxn];
12 
13 int dfn[maxn],low[maxn],Time;
14 int s[maxn],top,vis[maxn];
15 int f[maxn],n,m;
16 int cnt,belong[maxn],MAX[maxn];
17 int k,x[maxn],y[maxn],head[maxn];
18 
19 void add(int u,int v)
20 {
21     e[++k].to = v;
22     e[k].next = head[u];
23     head[u] = k;
24 }
25 
26 void tarjan(int x)                   //求有向图强联通分量的tarjan,在这里不过多叙述,想学习的可以点链接去博客qwq 
27 {
28     vis[x] = 1;
29     s[++top] = x;
30     dfn[x] = low[x] = ++Time;
31     for(int i = head[x];i;i=e[i].next)
32     {
33         int to = e[i].to;
34         if(!dfn[to])
35         {
36             tarjan(to);
37             low[x] = min(low[x],low[to]);
38         }
39         else if(vis[to])
40             low[x] = min(low[x],dfn[to]);
41     }
42     if(dfn[x] == low[x])            //如果x及其子树能够构成一个强联通分量 
43     {
44         ++cnt;
45         int j;
46         while(j=s[top])             //将其子树中的点都加入此分量中,并将此分量中的最大值保存在MAX数组中 
47         {
48             vis[j] = 0;
49             belong[j] = cnt;
50             MAX[cnt] = max(MAX[cnt],j);
51             top--;
52             if(j==x) break;
53         }
54     }
55 }
56 
57 void dfs(int x)                     //记忆化搜索 
58 {
59     if(f[x]) return;
60     f[x] = MAX[x];                  //当前强联通分量中的最大值 
61     for(int i=head[x];i;i=e[i].next)
62     {
63         int to = e[i].to;
64         if(!f[to]) dfs(to);
65         f[x] = max(f[x],f[to]);     // 子树中的最大值 
66     }
67 }
68 
69 int main()
70 {
71     //freopen("data.in","r",stdin);
72     //freopen("jkb.out","w",stdout);
73     scanf("%d%d",&n,&m);
74     for(int i=1;i<=m;i++)
75     {
76         scanf("%d%d",&x[i],&y[i]);          //保存边信息 
77         add(x[i],y[i]);
78     }
79     for(int i=1;i<=n;i++)                   //求出强联通分量 
80         if(!dfn[i])
81             tarjan(i);
82     memset(e,0,sizeof(e));                  //清空原图 
83     memset(head,0,sizeof(head));    
84     k = 0;
85     for(int i=1;i<=m;i++)                   //建立新图 
86         if(belong[x[i]]!=belong[y[i]])
87             add(belong[x[i]],belong[y[i]]);
88     for(int i=1;i<=cnt;i++)
89         if(!f[i]) dfs(i);
90     for(int i=1;i<=n;i++)                   //输出答案 
91         printf("%d ",f[belong[i]]);
92     return 0;
93 }

Guess you like

Origin www.cnblogs.com/doubeecat/p/10335591.html