hihor 學習日記:hihor一下 第五十四周(縮點+dfs)
阿新 • • 發佈:2018-12-30
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;
}