1. 程式人生 > >hihor 學習日記:hihor一下 第五十四周(縮點+dfs)

hihor 學習日記:hihor一下 第五十四周(縮點+dfs)

http://hihocoder.com/contest/hiho54/problem/1

這次是強連通分量
在這裡插入圖片描述
因為強連通分量是一個迴路,所以一張圖的一個強連通分量可以看成一個點,
虛擬碼:
在這裡插入圖片描述

AC程式碼:

#include <bits/stdc++.h>

using namespace std;
#define LL long long
const int Mod = 1e9 + 7;
const int maxn = 1e5 + 5;
const double eps = 0.00000001;
const int INF = 0x3f3f3f3f;

struct Edge{
    int
v, nxt; }edge[maxn << 1], edge2[maxn << 1]; int tot, tot2, head[maxn], head2[maxn]; int dfn[maxn], low[maxn], Stack[maxn], ifin[maxn], top, in[maxn], belong[maxn]; LL gra[maxn]; int counter = 0, cnt; LL num[maxn], sum; int N, M; void init(){ cnt = top = tot = tot2 = 0; memset(head,
-1, sizeof(head)); memset(ifin, 0, sizeof(ifin)); memset(head2, -1, sizeof(head2)); memset(num, 0, sizeof(num)); memset(dfn, 0, sizeof(dfn)); } void addEdge(int u, int v) { edge[tot].v = v; edge[tot].nxt = head[u]; head[u] = tot ++; } void addEdge2(int u, int v){ edge2[
tot2].v = v; edge2[tot2].nxt = head2[u]; head2[u] = tot2 ++; } void Tarjan(int u) { dfn[u] = low[u] = ++counter; Stack[++ top] = u; ifin[u] = 1; for (int i = head[u]; i + 1; i = edge[i].nxt) { int v = edge[i].v; if(!dfn[v]) { Tarjan(v); low[u] = min(low[u], low[v]); }else if(ifin[v]) { low[u] = min(low[u], dfn[v]); } } if(dfn[u] == low[u]) { cnt ++; do { ifin[Stack[top]] = 0; belong[Stack[top]] = cnt; }while(Stack[top --] != u); } } void dfs(int u, LL cc) { sum = max(sum, cc); for (int i = head2[u]; i + 1; i = edge2[i].nxt) { int v = edge2[i].v; dfs(v, cc + num[v]); } } void print() { for (int i = 1; i <= N; i ++) num[belong[i]] += gra[i]; for (int u = 1; u <= N; u ++) { for (int i = head[u]; i + 1; i = edge[i].nxt) { int v = edge[i].v; if(belong[u] != belong[v]) addEdge2(belong[u], belong[v]); } } sum = 0; dfs(belong[1], num[belong[1]]); cout << sum << endl; } int main() { init(); cin >> N >> M; for (int i = 1; i <= N; i ++) cin >> gra[i]; while(M --) { int u, v; cin >> u >> v; addEdge(u, v); } Tarjan(1); print(); return 0; }