Problem:
Problem K: Donuts Purchase
Problem
ラフイは休暇の間することがなく暇で、なんとなくドーナツが食べたくなったので、店を巡りドーナツを購入していくことにした。
各街には1軒のドーナツ店があり、すべてのドーナツ店は奇数日が定休日となっている。
ラフイにはドーナツの好みがあるので、店によって得られる満足度が違う。
そこでラフイは最適に行動することで、できるだけ多くの満足度を得ることにした。
ラフイが住んでいる世界には、それぞれ0から
n
-1の番号が割り当てられた
n
個の街があり、それらは
m
本の道で繋がれている。
それぞれの道は一方通行になっており、ラフイは街
a
i
から街
b
i
へ移動することができる。
最初ラフイは偶数日に街0にいる。
ラフイは街には留まらずに、1日に道を1本渡り別の街に移動する。
ラフイは街
i
に到着した日に、店が営業していれば1つドーナツを購入し、満足度
c
i
を得る。
同じ街は何度でも訪れることができるが、1つの店では1度しか購入しない。
ラフイがこれ以上満足度を得られない状態になるまで最適に行動した時の満足度の合計の最大を求めよ。
Input
n
m
c
0
...
c
n−1
a
0
b
0
...
a
m−1
b
m−1
入力はすべて整数で与えられる。
1行目に街の数
n
と道の数
m
が空白区切りで与えられる。
2行目に街
i
の店でドーナツを購入した際に得られる満足度
c
i
が空白区切りで与えられる。
続く
m
行に道の情報を表す
a
i
と
b
i
が空白区切りで与えられる。
Constraints
入力は以下の条件を満たす。
1 ≤
n
≤ 10
5
0 ≤
m
≤ min(
n
×(
n
−1),10
5
)
0 ≤
c
i
≤ 1000
0 ≤
a
i
,
b
i
≤
n
− 1
自己ループ、多重辺は存在しない
Output
満足度の合計の最大値を1行に出力せよ。
Sample Input 1
2 1
1 2
0 1
Sample Output 1
1
Sample Input 2
5 5
1 1 1 1 1
0 1
1 2
2 3
3 0
3 4
Sample Output 2
3
Sample Input 3
4 4
1 1 1 1
0 1
1 2
2 0
2 3
Sample Output 3
4

Submitted solutions:

code_snippet: // AOJ #3010 Donuts Purchase
// 2025.3.28

#include <bits/stdc++.h>
using namespace std;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)
using ll = long long;

int Cin() {
	int n = 0; int c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(int n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
    pc('\n');
}

const int MINF = -1000000000;

int main(){
    int n = Cin(), m = Cin();

    vector<int> c(n);
    for (int i = 0; i < n; i++) c[i] = Cin();

    int N = 2 * n;
    vector<vector<int>> g(N);
    for (int i = 0; i < m; i++){
        int a = Cin(), b = Cin();
        g[a].push_back(b + n);
        g[a + n].push_back(b);
    }

    vector<int> dfn(N, -1), low(N, -1), comp(N, -1);
    vector<bool> inStack(N, false);
    stack<int> st;
    int timeCnt = 0, compCnt = 0;

    function<void(int)> tarjan = [&](int u){
        dfn[u] = low[u] = timeCnt++;
        st.push(u);
        inStack[u] = true;
        for (int v : g[u]){
            if(dfn[v] == -1){
                tarjan(v);
                low[u] = min(low[u], low[v]);
            } else if(inStack[v]){
                low[u] = min(low[u], dfn[v]);
            }
        }
        if(low[u] == dfn[u]){
            while(true){
                int x = st.top(); st.pop();
                inStack[x] = false;
                comp[x] = compCnt;
                if(x == u) break;
            }
            compCnt++;
        }
    };

    for (int i = 0; i < N; i++){
        if(dfn[i] == -1) tarjan(i);
    }

    vector<int> w(compCnt, 0);
    for (int u = 0; u < n; u++) w[ comp[u] ] += c[u];

    vector<vector<int>> dag(compCnt);
    vector<int> indeg(compCnt, 0);
    for (int u = 0; u < N; u++){
        for (int v : g[u]){
            if(comp[u] != comp[v]){
                dag[ comp[u] ].push_back(comp[v]);
                indeg[ comp[v] ]++;
            }
        }
    }

    int s = comp[0];
    vector<int> dp(compCnt, MINF);
    dp[s] = w[s];

    queue<int> qu;
    for (int i = 0; i < compCnt; i++) if(indeg[i] == 0) qu.push(i);

    vector<int> topo;
    while(!qu.empty()){
        int u = qu.front(); qu.pop();
        topo.push_back(u);
        for (int v : dag[u]) if(--indeg[v] == 0) qu.push(v);
    }

    for (int u : topo){
        if(dp[u] == MINF) continue;
        for (int v : dag[u]) dp[v] = max(dp[v], dp[u] + w[v]);
    }

    int ans = 0;
    for (int i = 0; i < compCnt; i++) ans = max(ans, dp[i]);
    Cout(ans);
    return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 37288
final_rank: 1

code_snippet: // AOJ #3010 Donuts Purchase
// 2025.3.28

#include <bits/stdc++.h>
using namespace std;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)
using ll = long long;

int Cin() {
	int n = 0; int c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(int n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
    pc('\n');
}

int main(){
    int n = Cin(), m = Cin();

    vector<int> c(n);
    for (int i=0; i<n; i++) c[i] = Cin();

    int N = 2*n;
    vector<vector<int>> g(N), rg(N);
    for (int i=0; i<m; i++){
        int a = Cin(), b = Cin();
        g[a].push_back(b+n);
        rg[b+n].push_back(a);
        g[a+n].push_back(b);
        rg[b].push_back(a+n);
    }

    vector<bool> vis(N, false);
    vector<int> order(N), idx(N, 0);
    int pos = 0;
    for (int i=0; i<N; i++){
        if(!vis[i]){
            stack<int> st;
            st.push(i);
            while(!st.empty()){
                int u = st.top();
                if(!vis[u]) vis[u] = true;
                if (idx[u] < g[u].size()){
                    int v = g[u][idx[u]++];
                    if(!vis[v]) st.push(v);
                } else {
                    order[pos++] = u;
                    st.pop();
                }
            }
        }
    }

    vector<int> comp(N, -1);
    int compCount = 0;
    fill(vis.begin(), vis.end(), false);
    for (int i = N-1; i >= 0; i--){
        int u = order[i];
        if(!vis[u]){
            stack<int> st;
            st.push(u);
            vis[u] = true;
            comp[u] = compCount;
            while(!st.empty()){
                int x = st.top(); st.pop();
                for (int w: rg[x]){
                    if(!vis[w]){
                        vis[w] = true;
                        comp[w] = compCount;
                        st.push(w);
                    }
                }
            }
            compCount++;
        }
    }

    vector<int> w(compCount, 0);
    for (int u=0; u<N; u++){
        if(u < n) w[ comp[u] ] += c[u];
    }

    vector<vector<int>> dag(compCount);
    vector<int> indeg(compCount, 0);
    for (int u=0; u<N; u++){
        for (int v: g[u]){
            if(comp[u]!=comp[v]){
                dag[ comp[u] ].push_back(comp[v]);
                indeg[ comp[v] ]++;
            }
        }
    }

    int s = comp[0];
    const int MINF = -1000000000;
    vector<int> dp(compCount, MINF);
    dp[s] = w[s];

    vector<int> reach(compCount, 0);
    {
        queue<int> qu;
        qu.push(s);
        reach[s] = 1;
        while(!qu.empty()){
            int u = qu.front(); qu.pop();
            for (int v: dag[u]){
                if(!reach[v]){
                    reach[v] = 1;
                    qu.push(v);
                }
            }
        }
    }
    vector<int> indeg2(compCount, 0);
    for (int u=0; u<compCount; u++){
        if(!reach[u]) continue;
        for (int v: dag[u])
            if(reach[v]) indeg2[v]++;
    }
    queue<int> qu;
    vector<int> topo;
    for (int u=0; u<compCount; u++){
        if(reach[u] && indeg2[u]==0) qu.push(u);
    }
    while(!qu.empty()){
        int u = qu.front(); qu.pop();
        topo.push_back(u);
        for (int v: dag[u]){
            if(!reach[v]) continue;
            if(--indeg2[v]==0) qu.push(v);
        }
    }
    for (int u: topo){
        for (int v: dag[u]){
            if(!reach[v]) continue;
            dp[v] = max(dp[v], dp[u] + w[v]);
        }
    }
    int ans = 0;
    for (int i=0; i<compCount; i++){
        if(reach[i]) ans = max(ans, dp[i]);
    }
    Cout(ans);
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 43492
final_rank: 6

code_snippet: // AOJ #3010 Donuts Purchase
// 2025.3.24

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

#define gc() getchar_unlocked()
#define pc(c) putchar_unlocked(c)

int Cin() {
	int n = 0, c = gc();
	do n = 10*n + (c & 0xf), c = gc(); while (c >= '0');
	return n;
}

void Cout(ll n) {
	char b[30];
	if (!n) pc('0');
	else {
		if (n < 0) pc('-'), n = -n;
		int i = 0; while (n) b[i++] = n % 10 + '0', n /= 10;
		while (i--) pc(b[i]);
	}
	pc('\n');
}

vector<int> c;
vector<vector<int>> g;
vector<int> dfn, low, comp;
vector<bool> inStack;
stack<int> st;
int tcnt = 0, sccCnt = 0;

void tarjan(int u) {
    dfn[u] = low[u] = ++tcnt;
    st.push(u); inStack[u] = true;
    for(auto v: g[u]){
        if(dfn[v]==0){
            tarjan(v);
            low[u] = min(low[u], low[v]);
        } else if(inStack[v]) low[u] = min(low[u], dfn[v]);
    }
    if(low[u]==dfn[u]){
        while(true){
            int cur = st.top(); st.pop();
            inStack[cur] = false;
            comp[cur] = sccCnt;
            if(cur==u) break;
        }
        sccCnt++;
    }
}

int main(){
    int n = Cin(), m = Cin();
    c.resize(n);
    for(int i=0; i<n; i++) c[i] = Cin();
    g.resize(n);
    for(int i=0; i<m; i++){
        int u = Cin(), v = Cin();
        g[u].push_back(v);
    }

    dfn.assign(n,0); low.assign(n,0); comp.assign(n,-1);
    inStack.assign(n,false);
    for(int i=0; i<n; i++) if(dfn[i]==0) tarjan(i);

    vector<vector<int>> nodes(sccCnt);
    for(int i=0; i<n; i++) nodes[ comp[i] ].push_back(i);

    vector<set<int>> dset(sccCnt);
    for(int u=0; u<n; u++){
        for(auto v: g[u]){
            if(comp[u]!=comp[v]) dset[ comp[u] ].insert(comp[v]);
        }
    }
    vector<vector<int>> dag(sccCnt);
    for(int i=0; i<sccCnt; i++){
        for(auto j: dset[i]) dag[i].push_back(j);
    }

    vector<ll> tot(sccCnt,0), red(sccCnt,0), blue(sccCnt,0);
    vector<bool> bip(sccCnt, true);
    vector<int> col(n, -1);
    for(int i=0; i<sccCnt; i++){
        ll sum = 0;
        for(auto u: nodes[i]) { sum += c[u]; }
        tot[i] = sum;
        if(nodes[i].size()==1){
            int u = nodes[i][0];
            col[u] = 0;
            red[i] = c[u];
            blue[i] = -1e18;
        } else {
            for(auto u: nodes[i]) {
                if(col[u] == -1) {
                    col[u] = 0;
                    queue<int> qu; qu.push(u);
                    while(!qu.empty()){
                        int cur = qu.front(); qu.pop();
                        for(auto nxt: g[cur]){
                            if(comp[nxt]!= i) continue;
                            int want = col[cur]^1;
                            if(col[nxt]==-1){
                                col[nxt] = want;
                                qu.push(nxt);
                            } else if(col[nxt]!=want) bip[i] = false;
                        }
                    }
                }
            }
            if(bip[i]){
                ll s0 = 0, s1 = 0;
                for(auto u: nodes[i]){
                    if(col[u]==0) s0 += c[u];
                    else s1 += c[u];
                }
                red[i] = s0; blue[i] = s1;
            }
        }
    }

    const ll MINF = -1e18;
    vector<vector<ll>> dp(sccCnt, vector<ll>(2, MINF));
    vector<ll> ansVal(sccCnt, MINF);

    int r0 = comp[0];
    dp[r0][0] = 0;

    vector<int> indeg(sccCnt, 0);
    for(int i=0; i<sccCnt; i++){
        for(auto j: dag[i]) indeg[j]++;
    }
    queue<int> qu;
    vector<int> order;
    for(int i=0; i<sccCnt; i++) if(indeg[i]==0) qu.push(i);
    while(!qu.empty()){
        int u = qu.front(); qu.pop();
        order.push_back(u);
        for(auto v: dag[u]){
            indeg[v]--;
            if(indeg[v]==0) qu.push(v);
        }
    }

    for(auto u: order){
        if(nodes[u].size() == 1){
            int vtx = nodes[u][0];
            for(int p=0; p<2; p++){
                if(dp[u][p] == MINF) continue;
                ll cand = dp[u][p] + (p==0 ? c[vtx] : 0);
                ansVal[u] = max(ansVal[u], cand);
                for(auto v: dag[u]) dp[v][ p^1 ] = max(dp[v][ p^1 ], cand);
            }
        } else if(bip[u]){
            for(int p=0; p<2; p++){
                if(dp[u][p] == MINF) continue;
                ll candR = dp[u][p] + red[u];
                ll candB = dp[u][p] + blue[u];
                ansVal[u] = max({ansVal[u], candR, candB});
                for(auto v: dag[u]){
                    dp[v][0] = max(dp[v][0], candR);
                    dp[v][1] = max(dp[v][1], candB);
                }
            }
        } else {
            for(int p=0; p<2; p++){
                if(dp[u][p] == MINF) continue;
                ll cand = dp[u][p] + tot[u];
                ansVal[u] = max(ansVal[u], cand);
                for(auto v: dag[u]){
                    dp[v][0] = max(dp[v][0], cand);
                    dp[v][1] = max(dp[v][1], cand);
                }
            }
        }
    }

    ll ans = MINF;
    for(int i=0; i<sccCnt; i++){
        ans = max(ans, ansVal[i]);
        for(int p=0; p<2; p++) ans = max(ans, dp[i][p]);
    }
    Cout(ans);
    return 0;
}
accuracy: 0.55
time_ms: 20
memory_kb: 29936
final_rank: 11

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define NUM 100005

enum Type{
	UNDEFINED,
	A,
	B,
};

enum Which{
	EVEN,
	ODD,
};

struct GROUP{
	vector<int> nodes;
};

struct Edge{
	Edge(int arg_from_node,int arg_to_node){
		from_node = arg_from_node;
		to_node = arg_to_node;
	}
	int from_node,to_node;
};

struct Info{

	void set(int arg_start_node,int arg_sum_value,Which arg_start_which){
		start_node = arg_start_node;
		sum_value = arg_sum_value;
		start_which = arg_start_which;
	}
	bool operator<(const struct Info &arg) const{

		return sum_value < arg.sum_value; //総価値の降順(PQ)
	}

	int start_node,sum_value;
	Which start_which;
};

GROUP group[NUM]; //強連結成分のグループ
vector<int> G[NUM];
vector<int> reverse_G[NUM];
stack<int> S;
vector<Edge> Group_G[NUM];

bool check[NUM];
int V,E;
int value[NUM];
int table[NUM];
int group_index,sum_A[NUM],sum_B[NUM],sum_ALL[NUM];
int dp[NUM][2],in_num[NUM];
bool FLG,is_bipartie[NUM],can_go[NUM];
Type type[NUM],rev_type[3] = {UNDEFINED,B,A};
Which rev_which[2] = {ODD,EVEN};
priority_queue<Info> Q[NUM];


void dfs(int node_id){
	check[node_id] = true;

	for(int i = 0; i < G[node_id].size(); i++){
		if(!check[G[node_id][i]])dfs(G[node_id][i]);
	}
	S.push(node_id);
}

void reverse_dfs(int node_id){
	check[node_id] = true;

	group[group_index].nodes.push_back(node_id); //group[group_index]にノードを突っ込む
	table[node_id] = group_index;

	for(int i = 0; i < reverse_G[node_id].size(); i++){
		if(!check[reverse_G[node_id][i]])reverse_dfs(reverse_G[node_id][i]);
	}
}

void recursive(int node_id){

	if(!FLG)return;

	for(int i = 0; i < G[node_id].size(); i++){

		int next = G[node_id][i];

		if(table[next] != table[node_id])continue;

		if(type[next] == type[node_id]){

			FLG = false;
			return;

		}else if(type[next] == UNDEFINED){

			type[next] = rev_type[type[node_id]];
			recursive(next);

		}else{ //type[next] != type[node_id];

			//Do nothing
		}
	}
}

void make_can_go(int node_id){

	for(int i = 0; i < G[node_id].size(); i++){

		int next = G[node_id][i];
		if(can_go[next])continue;

		can_go[next] = true;
		make_can_go(next);
	}
}


int main(){

	scanf("%d %d",&V,&E);

	for(int i = 0; i < V; i++){

		scanf("%d",&value[i]);
	}

	int from,to;

	for(int loop = 0; loop < E; loop++){

		scanf("%d %d",&from,&to);

		G[from].push_back(to);
		reverse_G[to].push_back(from);
	}

	for(int i = 0; i < V; i++)check[i] = false;

	//まずは帰りがけ順を計算
	for(int i = 0; i < V;i++){
		if(!check[i])dfs(i);
	}

	for(int i = 0; i < V;i++)check[i] = false;

	group_index = -1;
	//ノードを、帰りがけ順の逆順に、各強連結成分(グループ)に分解
	while(!S.empty()){
		if(!check[S.top()]){
			group_index++;

			reverse_dfs(S.top());
		}
		S.pop();
	}

	for(int i = 0; i < V; i++){

		type[i] = UNDEFINED;
		in_num[i] = 0;
	}


	int tmp,tmp_A,tmp_B;

	//各グループ枚に2部グラフ判定
	for(int i = 0; i <= group_index; i++){

		FLG = true;
		type[group[i].nodes[0]] = A;
		recursive(group[i].nodes[0]);

		is_bipartie[i] = FLG;

		if(is_bipartie[i]){

			tmp_A = 0;
			tmp_B = 0;

			for(int k = 0; k < group[i].nodes.size(); k++){

				int tmp_node = group[i].nodes[k];

				if(type[tmp_node] == A){

					tmp_A += value[tmp_node];
				}else{

					tmp_B += value[tmp_node];
				}
			}

			sum_A[i] = tmp_A;
			sum_B[i] = tmp_B;

		}else{

			tmp = 0;

			for(int k = 0; k < group[i].nodes.size(); k++){

				int tmp_node = group[i].nodes[k];

				tmp += value[tmp_node];
			}

			sum_ALL[i] = tmp;
		}
	}

	for(int i = 0; i < V; i++){

		can_go[i] = false;
	}

	can_go[0] = true;
	make_can_go(0);

	for(int i = 0; i <= group_index; i++){
		for(int k = 0; k < group[i].nodes.size(); k++){

			int from_node = group[i].nodes[k];
			if(!can_go[from_node])continue; //ノード0から行けない街は無視

			for(int p = 0; p < G[from_node].size(); p++){
				int next_group = table[G[from_node][p]];
				if(next_group != i){

					Group_G[i].push_back(Edge(from_node,G[from_node][p]));
					in_num[next_group]++;
				}
			}
		}
	}

	for(int i = 0; i <= group_index; i++){

		dp[i][EVEN] = -BIG_NUM;
		dp[i][ODD] = -BIG_NUM;
	}


	Info first_info;

	int first_value;

	if(is_bipartie[table[0]]){ //出発ノードが2部グラフである場合

		if(type[0] == A){

			first_value = sum_A[table[0]];

		}else{

			first_value = sum_B[table[0]];
		}

	}else{

		first_value = sum_ALL[table[0]];
	}

	int ans = first_value;

	first_info.set(0,first_value,EVEN);
	Q[table[0]].push(first_info);

	queue<int> NODE;
	NODE.push(table[0]);
	vector<Which> WHICH;

	bool even_FLG,odd_FLG;

	while(!NODE.empty()){

		int current_group = NODE.front();
		NODE.pop();

		even_FLG = false;
		odd_FLG = false;

		while(Q[current_group].empty() == false && (even_FLG == false || odd_FLG == false)){

			Info info = Q[current_group].top();
			Q[current_group].pop();

			if(info.sum_value < dp[table[info.start_node]][info.start_which]){

				continue;

			}else{

				if(info.start_which == EVEN){

					even_FLG = true;
				}else{

					odd_FLG = true;
				}

				for(int i = 0; i < Group_G[current_group].size(); i++){

					int next_start = Group_G[current_group][i].to_node;
					int next_group = table[next_start];

					WHICH.clear();

					if(is_bipartie[current_group]){ //今のgroupが2部グラフ

						if(type[info.start_node] == type[Group_G[current_group][i].from_node]){

							WHICH.push_back(rev_which[info.start_which]);

						}else{

							WHICH.push_back(info.start_which);
						}

					}else{ //今のgroupが2部グラフでない

						WHICH.push_back(EVEN);
						WHICH.push_back(ODD);
					}

					int next_value = 0;

					for(int k = 0; k < WHICH.size(); k++){

						if(is_bipartie[next_group]){

							if(WHICH[k] == EVEN){

								if(type[next_start] == A){

									next_value = info.sum_value+sum_A[next_group];
								}else{

									next_value = info.sum_value+sum_B[next_value];
								}

							}else{ //WHICH[k] == ODD

								if(type[next_start] == A){

									next_value = info.sum_value+sum_B[next_group];
								}else{

									next_value = info.sum_value+sum_A[next_value];
								}
							}

						}else{ //次のgroupが2部グラフでない

							next_value = info.sum_value+sum_ALL[next_group];
						}

						if(dp[next_group][WHICH[k]] >= next_value)continue;

						dp[next_group][WHICH[k]] = next_value;
						ans = max(ans,next_value);
						Info next_info;
						next_info.set(next_start,next_value,WHICH[k]);
						Q[next_group].push(next_info);
					}
				}
			}
		}

		for(int i = 0; i < Group_G[current_group].size(); i++){

			int adj_node = Group_G[current_group][i].to_node;
			in_num[table[adj_node]]--;
			if(in_num[table[adj_node]] == 0){

				NODE.push(table[adj_node]);
			}
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 37932
final_rank: 4

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define NUM 100005

enum Type{
	UNDEFINED,
	A,
	B,
};

enum Which{
	EVEN,
	ODD,
};

struct GROUP{
	vector<int> nodes;
};

struct Edge{
	Edge(int arg_from_node,int arg_to_node){
		from_node = arg_from_node;
		to_node = arg_to_node;
	}
	int from_node,to_node;
};

struct Info{

	void set(int arg_start_node,int arg_sum_value,Which arg_start_which){
		start_node = arg_start_node;
		sum_value = arg_sum_value;
		start_which = arg_start_which;
	}
	bool operator<(const struct Info &arg) const{

		return sum_value < arg.sum_value; //総価値の降順(PQ)
	}

	int start_node,sum_value;
	Which start_which;
};

GROUP group[NUM]; //強連結成分のグループ
vector<int> G[NUM];
vector<int> reverse_G[NUM];
stack<int> S;
vector<Edge> Group_G[NUM];

bool check[NUM];
int V,E;
int value[NUM];
int table[NUM];
int group_index,sum_A[NUM],sum_B[NUM],sum_ALL[NUM];
int dp[NUM][2],in_num[NUM];
bool FLG,is_bipartie[NUM],can_go[NUM];
Type type[NUM],rev_type[3] = {UNDEFINED,B,A};
Which rev_which[2] = {ODD,EVEN};
priority_queue<Info> Q[NUM];


void dfs(int node_id){
	check[node_id] = true;

	for(int i = 0; i < G[node_id].size(); i++){
		if(!check[G[node_id][i]])dfs(G[node_id][i]);
	}
	S.push(node_id);
}

void reverse_dfs(int node_id){
	check[node_id] = true;

	group[group_index].nodes.push_back(node_id); //group[group_index]にノードを突っ込む
	table[node_id] = group_index;

	for(int i = 0; i < reverse_G[node_id].size(); i++){
		if(!check[reverse_G[node_id][i]])reverse_dfs(reverse_G[node_id][i]);
	}
}

void recursive(int node_id){

	if(!FLG)return;

	for(int i = 0; i < G[node_id].size(); i++){

		int next = G[node_id][i];

		if(table[next] != table[node_id])continue;

		if(type[next] == type[node_id]){

			FLG = false;
			return;

		}else if(type[next] == UNDEFINED){

			type[next] = rev_type[type[node_id]];
			recursive(next);

		}else{ //type[next] != type[node_id];

			//Do nothing
		}
	}
}

void make_can_go(int node_id){

	for(int i = 0; i < G[node_id].size(); i++){

		int next = G[node_id][i];
		if(can_go[next])continue;

		can_go[next] = true;
		make_can_go(next);
	}
}


int main(){

	scanf("%d %d",&V,&E);

	for(int i = 0; i < V; i++){

		scanf("%d",&value[i]);
	}

	int from,to;

	for(int loop = 0; loop < E; loop++){

		scanf("%d %d",&from,&to);

		G[from].push_back(to);
		reverse_G[to].push_back(from);
	}

	for(int i = 0; i < V; i++)check[i] = false;

	//まずは帰りがけ順を計算
	for(int i = 0; i < V;i++){
		if(!check[i])dfs(i);
	}

	for(int i = 0; i < V;i++)check[i] = false;

	group_index = -1;
	//ノードを、帰りがけ順の逆順に、各強連結成分(グループ)に分解
	while(!S.empty()){
		if(!check[S.top()]){
			group_index++;

			reverse_dfs(S.top());
		}
		S.pop();
	}

	for(int i = 0; i < V; i++){

		type[i] = UNDEFINED;
		in_num[i] = 0;
	}


	int tmp,tmp_A,tmp_B;

	//各グループ枚に2部グラフ判定
	for(int i = 0; i <= group_index; i++){

		FLG = true;
		type[group[i].nodes[0]] = A;
		recursive(group[i].nodes[0]);

		/*printf("\nグループ:%d\n",i);
		for(int k = 0; k < group[i].nodes.size(); k++){
			printf("%d\n",group[i].nodes[k]);
		}*/

		is_bipartie[i] = FLG;

		if(is_bipartie[i]){

			tmp_A = 0;
			tmp_B = 0;

			for(int k = 0; k < group[i].nodes.size(); k++){

				int tmp_node = group[i].nodes[k];

				if(type[tmp_node] == A){

					tmp_A += value[tmp_node];
				}else{

					tmp_B += value[tmp_node];
				}
			}

			sum_A[i] = tmp_A;
			sum_B[i] = tmp_B;

		}else{

			tmp = 0;

			for(int k = 0; k < group[i].nodes.size(); k++){

				int tmp_node = group[i].nodes[k];

				tmp += value[tmp_node];
			}

			sum_ALL[i] = tmp;
		}
	}

	for(int i = 0; i < V; i++){

		can_go[i] = false;
	}

	can_go[0] = true;
	make_can_go(0);

	for(int i = 0; i <= group_index; i++){
		for(int k = 0; k < group[i].nodes.size(); k++){

			int from_node = group[i].nodes[k];
			if(!can_go[from_node])continue; //ノード0から行けない街は無視

			for(int p = 0; p < G[from_node].size(); p++){
				int next_group = table[G[from_node][p]];
				if(next_group != i){

					//printf("from:%d next:%d from_G:%d next_G:%d\n",from_node,G[from_node][p],i,next_group);
					Group_G[i].push_back(Edge(from_node,G[from_node][p]));

					in_num[next_group]++;
				}
			}
		}
	}

	for(int i = 0; i <= group_index; i++){

		dp[i][EVEN] = -BIG_NUM;
		dp[i][ODD] = -BIG_NUM;
	}


	Info first_info;

	int first_value;

	if(is_bipartie[table[0]]){ //出発ノードが2部グラフである場合

		if(type[0] == A){

			first_value = sum_A[table[0]];

		}else{

			first_value = sum_B[table[0]];
		}

	}else{

		first_value = sum_ALL[table[0]];
	}

	int ans = first_value;

	first_info.set(0,first_value,EVEN);
	Q[table[0]].push(first_info);

	queue<int> NODE;
	NODE.push(table[0]);
	vector<Which> WHICH;

	while(!NODE.empty()){

		int current_group = NODE.front();
		NODE.pop();

		//printf("current:%d\n",current_group);

		while(!Q[current_group].empty()){

			Info info = Q[current_group].top();
			Q[current_group].pop();

			if(info.sum_value < dp[table[info.start_node]][info.start_which]){

				continue;

			}else{

				for(int i = 0; i < Group_G[current_group].size(); i++){

					int next_start = Group_G[current_group][i].to_node;
					int next_group = table[next_start];

					WHICH.clear();

					if(is_bipartie[current_group]){ //今のgroupが2部グラフ

						if(type[info.start_node] == type[Group_G[current_group][i].from_node]){

							WHICH.push_back(rev_which[info.start_which]);

						}else{

							WHICH.push_back(info.start_which);
						}

					}else{ //今のgroupが2部グラフでない

						WHICH.push_back(EVEN);
						WHICH.push_back(ODD);
					}

					int next_value = 0;

					for(int k = 0; k < WHICH.size(); k++){

						if(is_bipartie[next_group]){

							if(WHICH[k] == EVEN){

								if(type[next_start] == A){

									next_value = info.sum_value+sum_A[next_group];
								}else{

									next_value = info.sum_value+sum_B[next_value];
								}

							}else{ //WHICH[k] == ODD

								if(type[next_start] == A){

									next_value = info.sum_value+sum_B[next_group];
								}else{

									next_value = info.sum_value+sum_A[next_value];
								}
							}

						}else{ //次のgroupが2部グラフでない

							next_value = info.sum_value+sum_ALL[next_group];
						}

						if(dp[next_group][WHICH[k]] >= next_value)continue;

						dp[next_group][WHICH[k]] = next_value;
						ans = max(ans,next_value);
						Info next_info;
						next_info.set(next_start,next_value,WHICH[k]);
						Q[next_group].push(next_info);
					}
				}
			}
		}

		for(int i = 0; i < Group_G[current_group].size(); i++){

			int adj_node = Group_G[current_group][i].to_node;
			in_num[table[adj_node]]--;
			if(in_num[table[adj_node]] == 0){

				NODE.push(table[adj_node]);
			}
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 37984
final_rank: 5

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;



#define NUM 100005

enum Type{
	UNDEFINED,
	A,
	B,
};

enum Which{
	EVEN,
	ODD,
};

struct GROUP{
	vector<int> nodes;
};

struct Edge{
	Edge(int arg_from_node,int arg_to_node){
		from_node = arg_from_node;
		to_node = arg_to_node;
	}
	int from_node,to_node;
};

struct Info{

	void set(int arg_start_node,int arg_sum_value,Which arg_start_which){
		start_node = arg_start_node;
		sum_value = arg_sum_value;
		start_which = arg_start_which;
	}
	bool operator<(const struct Info &arg) const{

		return sum_value < arg.sum_value; //総価値の降順(PQ)
	}

	int start_node,sum_value;
	Which start_which;
};

GROUP group[NUM]; //強連結成分のグループ
vector<int> G[NUM];
vector<int> reverse_G[NUM];
stack<int> S;
vector<Edge> Group_G[NUM];

bool check[NUM];
int V,E;
int value[NUM];
int table[NUM];
int group_index,sum_A[NUM],sum_B[NUM],sum_ALL[NUM];
int dp[NUM][2];
bool FLG,is_bipartie[NUM];
Type type[NUM],rev_type[3] = {UNDEFINED,B,A};
Which rev_which[2] = {ODD,EVEN};


void dfs(int node_id){
	check[node_id] = true;

	for(int i = 0; i < G[node_id].size(); i++){
		if(!check[G[node_id][i]])dfs(G[node_id][i]);
	}
	S.push(node_id);
}

void reverse_dfs(int node_id){
	check[node_id] = true;

	group[group_index].nodes.push_back(node_id); //group[group_index]にノードを突っ込む
	table[node_id] = group_index;

	for(int i = 0; i < reverse_G[node_id].size(); i++){
		if(!check[reverse_G[node_id][i]])reverse_dfs(reverse_G[node_id][i]);
	}
}

void recursive(int node_id){

	if(!FLG)return;

	for(int i = 0; i < G[node_id].size(); i++){

		int next = G[node_id][i];

		if(table[next] != table[node_id])continue;

		if(type[next] == type[node_id]){

			FLG = false;
			return;

		}else if(type[next] == UNDEFINED){

			type[next] = rev_type[type[node_id]];
			recursive(next);

		}else{ //type[next] != type[node_id];

			//Do nothing
		}
	}
}


int main(){

	scanf("%d %d",&V,&E);

	for(int i = 0; i < V; i++){

		scanf("%d",&value[i]);
	}

	int from,to;

	for(int loop = 0; loop < E; loop++){

		scanf("%d %d",&from,&to);

		G[from].push_back(to);
		reverse_G[to].push_back(from);
	}

	for(int i = 0; i < V; i++)check[i] = false;

	//まずは帰りがけ順を計算
	for(int i = 0; i < V;i++){
		if(!check[i])dfs(i);
	}

	for(int i = 0; i < V;i++)check[i] = false;

	group_index = -1;
	//ノードを、帰りがけ順の逆順に、各強連結成分(グループ)に分解
	while(!S.empty()){
		if(!check[S.top()]){
			group_index++;

			reverse_dfs(S.top());
		}
		S.pop();
	}

	for(int i = 0; i < V; i++){

		type[i] = UNDEFINED;
	}


	int tmp,tmp_A,tmp_B;

	//各グループ枚に2部グラフ判定
	for(int i = 0; i <= group_index; i++){

		FLG = true;
		type[group[i].nodes[0]] = A;
		recursive(group[i].nodes[0]);

		is_bipartie[i] = FLG;

		if(is_bipartie[i]){

			tmp_A = 0;
			tmp_B = 0;

			for(int k = 0; k < group[i].nodes.size(); k++){

				int tmp_node = group[i].nodes[k];

				if(type[tmp_node] == A){

					tmp_A += value[tmp_node];
				}else{

					tmp_B += value[tmp_node];
				}
			}

			sum_A[i] = tmp_A;
			sum_B[i] = tmp_B;

		}else{

			tmp = 0;

			for(int k = 0; k < group[i].nodes.size(); k++){

				int tmp_node = group[i].nodes[k];

				tmp += value[tmp_node];
			}

			sum_ALL[i] = tmp;
		}
	}

	for(int i = 0; i <= group_index; i++){
		for(int k = 0; k < group[i].nodes.size(); k++){

			int from_node = group[i].nodes[k];

			for(int p = 0; p < G[from_node].size(); p++){
				int next_group = table[G[from_node][p]];
				if(next_group != i){

					//printf("%d-%d\n",from_node,G[from_node][p]);
					Group_G[i].push_back(Edge(from_node,G[from_node][p]));
				}
			}
		}
	}

	for(int i = 0; i <= group_index; i++){

		dp[i][EVEN] = -BIG_NUM;
		dp[i][ODD] = -BIG_NUM;
	}

	priority_queue<Info> Q;
	Info first_info;

	int first_value;

	if(is_bipartie[table[0]]){ //出発ノードが2部グラフである場合

		if(type[0] == A){

			first_value = sum_A[table[0]];

		}else{

			first_value = sum_B[table[0]];
		}

	}else{

		first_value = sum_ALL[table[0]];
	}

	int ans = first_value;

	first_info.set(0,first_value,EVEN);
	Q.push(first_info);

	vector<Which> WHICH;

	while(!Q.empty()){

		Info info = Q.top();
		Q.pop();

		if(info.sum_value < dp[table[info.start_node]][info.start_which]){

			continue;

		}else{

			int current_group = table[info.start_node];
			WHICH.clear();

			for(int i = 0; i < Group_G[current_group].size(); i++){

				int next_start = Group_G[current_group][i].to_node;
				int next_group = table[next_start];

				if(is_bipartie[current_group]){ //今のgroupが2部グラフ

					if(type[info.start_node] == type[Group_G[current_group][i].from_node]){

						WHICH.push_back(rev_which[info.start_which]);

					}else{

						WHICH.push_back(info.start_which);
					}

				}else{ //今のgroupが2部グラフでない

					WHICH.push_back(EVEN);
					WHICH.push_back(ODD);
				}

				int next_value = 0;

				for(int k = 0; k < WHICH.size(); k++){

					if(is_bipartie[next_group]){

						if(WHICH[k] == EVEN){

							if(type[next_start] == A){

								next_value = info.sum_value+sum_A[next_group];
							}else{

								next_value = info.sum_value+sum_B[next_value];
							}

						}else{ //WHICH[k] == ODD

							if(type[next_start] == A){

								next_value = info.sum_value+sum_B[next_group];
							}else{

								next_value = info.sum_value+sum_A[next_value];
							}
						}

					}else{ //次のgroupが2部グラフでない

						next_value = info.sum_value+sum_ALL[next_group];
					}

					if(dp[next_group][WHICH[k]] >= next_value)continue;

					dp[next_group][WHICH[k]] = next_value;
					ans = max(ans,next_value);
					Info next_info;
					next_info.set(next_start,next_value,WHICH[k]);
					Q.push(next_info);
				}
			}
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 0.575
time_ms: 210
memory_kb: 18964
final_rank: 10

code_snippet: #include<iostream>
#include<vector>
#include<string>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<functional>
#include<iomanip>
#include<queue>
#include<ciso646>
#include<utility>
#include<set>
#include<map>
#include<stack>
using namespace std;
typedef long long ll;
const ll mod = 1000000007;
const ll INF = mod * mod;
typedef pair<int, int> P;
typedef pair<ll, ll> LP;
typedef vector<int> vec;
typedef long double ld;
#define rep(i,n) for(int i=0;i<n;i++)
#define per(i,n) for(int i=n-1;i>=0;i--)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define Rep(i,sta,n) for(int i=sta;i<n;i++)
#define stop char nyaa;cin>>nyaa;

struct graph{
private:
	int n;
	vector<vector<int>> G, rG;
	vector<bool> used;
	vector<int> vs;

	int mk;
	vector<vector<int>> fG;
	vector <vector<int>> ori;
	vector<int> trans;

	vector<ll> cost;
	vector<ll> memo;

public:
	graph(int sz) {
		n = sz;
		G.resize(n);
		rG.resize(n);
		used.resize(n);

		fG.resize(n);
		trans.resize(n, -1);
		ori.resize(n);
	}
	void add_edge(int a, int b) {
		G[a].push_back(b);
		rG[b].push_back(a);
	}
	void dfs(int v) {
		used[v] = true;
		rep(i, G[v].size()) {
			if (!used[G[v][i]])dfs(G[v][i]);
		}
		vs.push_back(v);
	}
	void rdfs(int v, int k) {
		used[v] = true;
		queue<int> q; q.push(v);
		vector<int> c;
		while (!q.empty()) {
			int id = q.front(); q.pop();
			ori[k].push_back(id);
			rep(j, rG[id].size()) {
				int to = rG[id][j];
				if (used[to]) {
					if (trans[to] >= 0)c.push_back(trans[to]);
					continue;
				}
				used[to] = true;
				q.push(to);
			}
		}
		sort(c.begin(), c.end());
		int len = unique(c.begin(), c.end()) - c.begin();
		rep(i, len) {
			fG[c[i]].push_back(k);
		}
		rep(i, ori[k].size()) {
			trans[ori[k][i]] = k;
		}
	}
	void scc() {
		fill(used.begin(), used.end(), false);
		rep(i, n) {
			if (!used[i])dfs(i);
		}
		fill(used.begin(), used.end(), false);
		int k = 0;
		per(i, (int)vs.size()) {
			if (!used[vs[i]]) {
				rdfs(vs[i], k); k++;
			}
		}
		mk = k;
	}
	void give_val(vector<ll> &v) {
		cost.resize(mk);
		rep(i, v.size()) {
			cost[trans[i]] += v[i];
		}
	}
	ll qdfs(int id) {
		if (used[id])return memo[id];
		used[id] = true;
		ll ret = 0;
		rep(j, fG[id].size()) {
			int to = fG[id][j];
			ll nex = qdfs(to);
			ret = max(ret, nex);
		}
		return memo[id]=ret + cost[id];
	}
	ll query() {
		fill(used.begin(), used.end(),false);
		memo.resize(mk);
		int sta = trans[0];
		return qdfs(sta);
	}
};
void solve() {
	int n, m;
	cin >> n >> m;
	vector<ll> c(n);
	rep(i, n)cin >> c[i];
	graph g(2*n);
	rep(i, m) {
		int a, b; cin >> a >> b;
		g.add_edge(a, b + n);
		g.add_edge(a + n, b);
	}
	g.scc(); g.give_val(c);
	ll ans = g.query();
	cout << ans << endl;
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	//cout << fixed << setprecision(6);
	solve();
	//stop
		return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 55592
final_rank: 8

code_snippet: #include <bits/stdc++.h>

using namespace std;


template< typename T >
struct edge {
  int src, to;
  T cost;

  edge(int to, T cost) : src(-1), to(to), cost(cost) {}

  edge(int src, int to, T cost) : src(src), to(to), cost(cost) {}

  edge &operator=(const int &x) {
    to = x;
    return *this;
  }

  operator int() const { return to; }
};

template< typename T >
using Edges = vector< edge< T > >;
template< typename T >
using WeightedGraph = vector< Edges< T > >;
using UnWeightedGraph = vector< vector< int > >;
template< typename T >
using Matrix = vector< vector< T > >;

template< typename G >
struct StronglyConnectedComponents {
  const G &g;
  UnWeightedGraph gg, rg;
  vector< int > comp, order, used;

  StronglyConnectedComponents(G &g) : g(g), gg(g.size()), rg(g.size()), comp(g.size(), -1), used(g.size()) {
    for(int i = 0; i < g.size(); i++) {
      for(auto e : g[i]) {
        gg[i].emplace_back((int) e);
        rg[(int) e].emplace_back(i);
      }
    }
  }

  int operator[](int k) {
    return comp[k];
  }

  void dfs(int idx) {
    if(used[idx]) return;
    used[idx] = true;
    for(int to : gg[idx]) dfs(to);
    order.push_back(idx);
  }

  void rdfs(int idx, int cnt) {
    if(comp[idx] != -1) return;
    comp[idx] = cnt;
    for(int to : rg[idx]) rdfs(to, cnt);
  }

  void build(UnWeightedGraph &t) {
    for(int i = 0; i < gg.size(); i++) dfs(i);
    reverse(begin(order), end(order));
    int ptr = 0;
    for(int i : order) if(comp[i] == -1) rdfs(i, ptr), ptr++;

    t.resize(ptr);
    for(int i = 0; i < g.size(); i++) {
      for(auto &to : g[i]) {
        int x = comp[i], y = comp[to];
        if(x == y) continue;
        t[x].push_back(y);
      }
    }
  }
};

const int INF = 1 << 30;


int main() {
  int N, M, C[100000];
  cin >> N >> M;
  for(int i = 0; i < N; i++) cin >> C[i];
  UnWeightedGraph g(N * 2);
  for(int i = 0; i < M; i++) {
    int a, b;
    cin >> a >> b;
    a *= 2;
    b *= 2;
    for(int j = 0; j < 2; j++) {
      g[a + j].emplace_back(b + (j + 1) % 2);
    }
  }
  StronglyConnectedComponents< UnWeightedGraph > scc(g);
  UnWeightedGraph t;
  scc.build(t);
  int belong[200000] = {};
  for(int i = 0; i < N; i++) belong[scc[2 * i]] += C[i];
  vector< int > dp(t.size(), -INF);
  dp[scc[0]] = belong[scc[0]];
  for(int i = 0; i < t.size(); i++) {
    for(auto &p : t[i]) dp[p] = max(dp[p], dp[i] + belong[p]);
  }
  cout << *max_element(begin(dp), end(dp)) << endl;
}
accuracy: 1
time_ms: 90
memory_kb: 53232
final_rank: 7

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
struct Dscc {
public:

	//fst:belongs , scd:newedges
	pair<vector<vector<int>>, vector<vector<int>>>get(const vector<vector<int>>&edges) {
		nums.resize(edges.size());
		fill(nums.begin(), nums.end(), -1);
		vector<vector<int>>revedges(edges.size());
		for (int i = 0; i < edges.size(); ++i) {
			for (auto j : edges[i]) {
				revedges[j].push_back(i);
			}
		}
		int num = 0;
		for (int i = 0; i < edges.size(); ++i) {
			dfs(i, num, edges);
		}
		vector<int>big(nums.size());
		for (int i = 0; i < nums.size(); ++i) {
			big[nums[i]] = i;
		}
		reverse(big.begin(), big.end());
		unis.resize(edges.size());
		fill(unis.begin(), unis.end(), -1);
		num = 0;
		for (int i = 0; i < big.size(); ++i) {

			dfs2(big[i], num, revedges);
			num++;
		}
		vector<int>nums;
		for (int i = 0; i < unis.size(); ++i) {
			nums.push_back(unis[i]);
		}
		sort(nums.begin(), nums.end());
		nums.erase(unique(nums.begin(), nums.end()), nums.end());


		map<int, int>mp;
		for (int i = 0; i < nums.size(); ++i) {
			mp[nums[i]] = i;
		}
		for (int i = 0; i < unis.size(); ++i) {
			unis[i] = mp[unis[i]];
		}

		vector<vector<int>>belongs(nums.size());
		for (int i = 0; i < unis.size(); ++i) {
			belongs[unis[i]].push_back(i);
		}
		vector<vector<int>>newedges(nums.size());
		for (int i = 0; i < edges.size(); ++i) {
			for (auto j : edges[i]) {
				if (unis[i] != unis[j]) {
					newedges[unis[i]].push_back(unis[j]);
				}
			}
		}
		return make_pair(belongs, newedges);
	}
public:
	vector<int>nums;
	vector<int>unis;


	void dfs(const int id, int &num, const vector<vector<int>>&edges) {
		if (nums[id] != -1)return;
		else {
			nums[id] = -2;
			for (auto i : edges[id]) {
				dfs(i, num, edges);
			}
		}
		nums[id] = num++;
		return;
	}
	void dfs2(const int id, const int &num, const vector<vector<int>>&edges) {
		if (unis[id] != -1)return;
		else {
			unis[id] = -2;
			for (auto i : edges[id])
				dfs2(i, num, edges);
		}
		unis[id] = num;
		return;
	}

}dscc;

void dfs(const int now, const vector<vector<int>>&edges, vector<int>&colors,int num) {
	colors[now]=num;
	for (auto e : edges[now]) {
		if(dscc.unis[now]!=dscc.unis[e])continue;
		else {
			if (num != 2) {
				if (colors[e] == num) {
					dfs(e, edges, colors, 2);
					
				}
				else if (colors[e] + num == 1) {

				}
				else if(colors[e]!=2){
					dfs(e,edges,colors,!num);
				}
			}
			else {
				if (colors[e] == 2) {

				}
				else {
					dfs(e,edges,colors,2);
				}
			}
			
		}
	}
}

void cango(const int now, const vector<vector<int>>&edges,vector<int>&can) {
	can[now]=true;
	for (auto e : edges[now]) {
		if(!can[e])cango(e,edges,can);
	}
}
int main() {
	int N,M;
	vector<int>cs;
	cin >> N >> M;
	vector<vector<int>>edges(N);
	{
		for (int i = 0; i < N; ++i) {
			int a; cin >> a;
			cs.push_back(a);
		}
		for (int i = 0; i < M; ++i) {
			int a, b; cin >> a >> b;
			edges[a].push_back(b);
		}
		vector<int>can(N);
		cango(0, edges, can);
		map<int,int>mp;
		int id=0;
		vector<int>ncs;
		for (int i = 0; i < N; ++i) {
			if (can[i]) {
				mp[i] = id++;
				ncs.push_back(cs[i]);
			}
		}
		vector<vector<int>>nedges(ncs.size());
		for (int i = 0; i < N; ++i) {
			if (can[i]) {
				for (int j = 0; j < edges[i].size(); ++j) {
					if (can[i] && can[edges[i][j]]) {
						nedges[mp[i]].push_back(mp[edges[i][j]]);
					}
				}
			}
		}
		cs=ncs;
		edges=nedges;
		N=cs.size();
	}
	
	auto p=dscc.get(edges);
	vector<int>colors(N,-1);
	for (int i = 0; i < N; ++i) {
		if (colors[i] == -1) {

			dfs(i, edges, colors, 0);
		}
	}

	vector<vector<pair<int,bool>>>nextedges(p.second.size());
	vector<vector<int>>sums(p.second.size(),vector<int>(2));
	vector<int>comes(p.second.size());
	vector<int>biparates(p.second.size());
	for (int i = 0; i < N; ++i) {
		if (colors[i] == 2) {
			sums[dscc.unis[i]][0]+=cs[i];
			biparates[dscc.unis[i]]=false;
		}
		else {
			biparates[dscc.unis[i]]=true;
			sums[dscc.unis[i]][colors[i]]+=cs[i];
			
		}
		for (auto e : edges[i]) {
			if (dscc.unis[i] != dscc.unis[e]) {
				const int from=dscc.unis[i];
				const int to=dscc.unis[e];
				if (colors[i] == 2 || colors[e] == 2) {
					nextedges[from].push_back(make_pair(to,true));
				}
				else {
					nextedges[from].push_back(make_pair(to,colors[i]==colors[e]));
				}
				comes[to]--;
			}
		}
	}
	queue<int>que;
	vector<vector<int>>memo(p.second.size(),vector<int>(2,-1e9));


	memo[0][0]=sums[0][0];
	que.push(0);
		
	
	while (!que.empty()) {
		const int now=que.front();
		que.pop();
		for (auto e : nextedges[now]) {
			const int next=e.first;
			comes[next]++;
			if(!comes[next])que.push(next);
			if (!biparates[next]) {
				const int nextcost=max(memo[now][0],memo[now][1])+sums[next][0];
				if (nextcost > memo[next][0]) {
					memo[next][0]=nextcost;
				}
			}
			else if(!biparates[now]){
				for (int i = 0; i < 2; ++i) {
					const int nextcost=memo[now][0]+sums[next][i];
					if (nextcost > memo[next][i]) {
						memo[next][i]=nextcost;
					}
				}
			}
			else {
				for (int i = 0; i < 2; ++i) {
					if (!e.second) {
						const int nextcost = memo[now][i] + sums[next][i];
						if (nextcost > memo[next][i]) {
							memo[next][i] = nextcost;
						}
					}
					else {
						const int nextcost=memo[now][i]+sums[next][!i];
						if (nextcost > memo[next][!i]) {
							memo[next][!i]=nextcost;
						}
					}
				}
			}
		}
	}
	int ans=0;
	for (int i = 0; i < memo.size(); ++i) {
		for (int j = 0; j < 2; ++j) {
			ans=max(ans,memo[i][j]);
		}
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 1
time_ms: 150
memory_kb: 47228
final_rank: 9

code_snippet: #include "bits/stdc++.h"
#include<unordered_map>
#include<unordered_set>
#pragma warning(disable:4996)
using namespace std;
struct Dscc {
public:

	//fst:belongs , scd:newedges
	pair<vector<vector<int>>, vector<vector<int>>>get(const vector<vector<int>>&edges) {
		nums.resize(edges.size());
		fill(nums.begin(), nums.end(), -1);
		vector<vector<int>>revedges(edges.size());
		for (int i = 0; i < edges.size(); ++i) {
			for (auto j : edges[i]) {
				revedges[j].push_back(i);
			}
		}
		int num = 0;
		for (int i = 0; i < edges.size(); ++i) {
			dfs(i, num, edges);
		}
		vector<int>big(nums.size());
		for (int i = 0; i < nums.size(); ++i) {
			big[nums[i]] = i;
		}
		reverse(big.begin(), big.end());
		unis.resize(edges.size());
		fill(unis.begin(), unis.end(), -1);
		num = 0;
		for (int i = 0; i < big.size(); ++i) {

			dfs2(big[i], num, revedges);
			num++;
		}
		vector<int>nums;
		for (int i = 0; i < unis.size(); ++i) {
			nums.push_back(unis[i]);
		}
		sort(nums.begin(), nums.end());
		nums.erase(unique(nums.begin(), nums.end()), nums.end());


		map<int, int>mp;
		for (int i = 0; i < nums.size(); ++i) {
			mp[nums[i]] = i;
		}
		for (int i = 0; i < unis.size(); ++i) {
			unis[i] = mp[unis[i]];
		}

		vector<vector<int>>belongs(nums.size());
		for (int i = 0; i < unis.size(); ++i) {
			belongs[unis[i]].push_back(i);
		}
		vector<vector<int>>newedges(nums.size());
		for (int i = 0; i < edges.size(); ++i) {
			for (auto j : edges[i]) {
				if (unis[i] != unis[j]) {
					newedges[unis[i]].push_back(unis[j]);
				}
			}
		}
		return make_pair(belongs, newedges);
	}
public:
	vector<int>nums;
	vector<int>unis;


	void dfs(const int id, int &num, const vector<vector<int>>&edges) {
		if (nums[id] != -1)return;
		else {
			nums[id] = -2;
			for (auto i : edges[id]) {
				dfs(i, num, edges);
			}
		}
		nums[id] = num++;
		return;
	}
	void dfs2(const int id, const int &num, const vector<vector<int>>&edges) {
		if (unis[id] != -1)return;
		else {
			unis[id] = -2;
			for (auto i : edges[id])
				dfs2(i, num, edges);
		}
		unis[id] = num;
		return;
	}

}dscc;

void dfs(const int now, const vector<vector<int>>&edges, vector<int>&colors,int num) {
	colors[now]=num;
	for (auto e : edges[now]) {
		if(dscc.unis[now]!=dscc.unis[e])continue;
		else {
			if (num != 2) {
				if (colors[e] == num) {
					dfs(e, edges, colors, 2);
				}
				else if (colors[e] + num == 1) {

				}
				else {
					dfs(e,edges,colors,!num);
				}
			}
			else {
				if (colors[e] == 2) {

				}
				else {
					dfs(e,edges,colors,2);
				}
			}
			
		}
	}
}

void cango(const int now, const vector<vector<int>>&edges,vector<int>&can) {
	can[now]=true;
	for (auto e : edges[now]) {
		if(!can[e])cango(e,edges,can);
	}
}
int main() {
	int N,M;
	vector<int>cs;
	cin >> N >> M;
	vector<vector<int>>edges(N);
	{
		for (int i = 0; i < N; ++i) {
			int a; cin >> a;
			cs.push_back(a);
		}
		for (int i = 0; i < M; ++i) {
			int a, b; cin >> a >> b;
			edges[a].push_back(b);
		}
		vector<int>can(N);
		cango(0, edges, can);
		map<int,int>mp;
		int id=0;
		vector<int>ncs;
		for (int i = 0; i < N; ++i) {
			if (can[i]) {
				mp[i] = id++;
				ncs.push_back(cs[i]);
			}
		}
		vector<vector<int>>nedges(ncs.size());
		for (int i = 0; i < N; ++i) {
			if (can[i]) {
				for (int j = 0; j < edges[i].size(); ++j) {
					if (can[i] && can[edges[i][j]]) {
						nedges[mp[i]].push_back(mp[edges[i][j]]);
					}
				}
			}
		}
		cs=ncs;
		edges=nedges;
		N=cs.size();
	}
	
	auto p=dscc.get(edges);
	vector<int>colors(N,-1);
	for (int i = 0; i < N; ++i) {
		if (colors[i] == -1) {

			dfs(i, edges, colors, 0);
		}
	}

	vector<vector<pair<int,bool>>>nextedges(p.second.size());
	vector<vector<int>>sums(p.second.size(),vector<int>(2));
	vector<int>comes(p.second.size());
	vector<int>biparates(p.second.size());
	for (int i = 0; i < N; ++i) {
		if (colors[i] == 2) {
			sums[dscc.unis[i]][0]+=cs[i];
			biparates[dscc.unis[i]]=false;
		}
		else {
			biparates[dscc.unis[i]]=true;
			sums[dscc.unis[i]][colors[i]]+=cs[i];
			
		}
		for (auto e : edges[i]) {
			if (dscc.unis[i] != dscc.unis[e]) {
				const int from=dscc.unis[i];
				const int to=dscc.unis[e];
				if (colors[i] == 2 || colors[e] == 2) {
					nextedges[from].push_back(make_pair(to,true));
				}
				else {
					nextedges[from].push_back(make_pair(to,colors[i]==colors[e]));
				}
				comes[to]--;
			}
		}
	}
	queue<int>que;
	vector<vector<int>>memo(p.second.size(),vector<int>(2,-1e9));


	memo[0][0]=sums[0][0];
	que.push(0);
		
	
	while (!que.empty()) {
		const int now=que.front();
		que.pop();
		for (auto e : nextedges[now]) {
			const int next=e.first;
			comes[next]++;
			if(!comes[next])que.push(next);
			if (!biparates[next]) {
				const int nextcost=max(memo[now][0],memo[now][1])+sums[next][0];
				if (nextcost > memo[next][0]) {
					memo[next][0]=nextcost;
				}
			}
			else if(!biparates[now]){
				for (int i = 0; i < 2; ++i) {
					const int nextcost=memo[now][0]+sums[next][i];
					if (nextcost > memo[next][i]) {
						memo[next][i]=nextcost;
					}
				}
			}
			else {
				for (int i = 0; i < 2; ++i) {
					if (!e.second) {
						const int nextcost = memo[now][i] + sums[next][i];
						if (nextcost > memo[next][i]) {
							memo[next][i] = nextcost;
						}
					}
					else {
						const int nextcost=memo[now][i]+sums[next][!i];
						if (nextcost > memo[next][!i]) {
							memo[next][!i]=nextcost;
						}
					}
				}
			}
		}
	}
	int ans=0;
	for (int i = 0; i < memo.size(); ++i) {
		for (int j = 0; j < 2; ++j) {
			ans=max(ans,memo[i][j]);
		}
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 0.325
time_ms: 130
memory_kb: 75316
final_rank: 20

code_snippet: #include "bits/stdc++.h"
using namespace std;

void dfs(vector<int>&colors,const int now, const vector<vector<int>>&edges) {
	if (colors[now] == 0) {
		for (auto e : edges[now]) {
			if(colors[e]==1)continue;
			else if (colors[e] == 0) {
				colors[e]=2;
				dfs(colors,e,edges);
			}
			else if (colors[e] == 2) {
				continue;
			}
			else if (colors[e] == -1) {
				colors[e]=1;
				dfs(colors,e,edges);
			}
		}
	}
	else if (colors[now] == 1) {
		for (auto e : edges[now]) {
			if (colors[e] == 0)continue;
			else if (colors[e] == 1) {
				colors[e] = 2;
				dfs(colors, e, edges);
			}
			else if (colors[e] == 2) {
				continue;
			}
			else if (colors[e] == -1) {
				colors[e] = 0;
				dfs(colors, e, edges);
			}
		}
	}else{
		for (auto e : edges[now]) {
			if (colors[e] ==2)continue;
			
			else{
				colors[e] = 2;
				dfs(colors, e, edges);
			}
		}
	}
}

int main() { 
	int N,M;cin>>N>>M;
	vector<long long int>cs(N);
	for (int i = 0; i < N; ++i) {
		cin>>cs[i];
	}
	vector<vector<int>>edges(N);
	for (int i = 0; i < M; ++i) {
		int a,b;cin>>a>>b;
		edges[a].push_back(b);
	}
	vector<int>colors(N,-1);
	colors[0]=0;
	dfs(colors,0,edges);
	long long int ans=0;
	for (int i = 0; i < N; ++i) {
		if(colors[i]==0||colors[i]==2)ans+=cs[i];
	}
	cout<<ans<<endl;
	return 0;
}
accuracy: 0.325
time_ms: 40
memory_kb: 6500
final_rank: 14

code_snippet: #include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <string>
#include <algorithm>
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <functional>
#include <iostream>
#define MOD 1000000007LL
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> PP;

int n,m;
int c[100001];
int f[100001],t[100001];
vector<int> G[100001];
vector<int> rG[100001];
vector<int> vs;
vector<int> lis[100001];
bool used[100001];
int cmp[100001]; 
bool notbi[100001];
int color[100001];
int sum[100001][2];
int dp[100001][2][2];
vector<PP> sccG[100001];

void dfs(int v){
	used[v]=true;
	for(int i=0;i<G[v].size();i++){
		if(!used[G[v][i]])dfs(G[v][i]);
	}
	vs.push_back(v);
}

void rdfs(int v,int k){
	used[v]=true;
	cmp[v]=k;
	lis[k].push_back(v);
	for(int i=0;i<rG[v].size();i++){
		if(!used[rG[v][i]])rdfs(rG[v][i],k);
	}
}

int scc(){
	memset(used,false,sizeof(used));
	vs.clear();
	for(int v=0;v<n;v++){
		if(!used[v])dfs(v);
	}
	memset(used,false,sizeof(used));
	int k=0;
	for(int i=vs.size()-1;i>=0;i--){
		if(!used[vs[i]])rdfs(vs[i],k++);
	}
	return k;
}

bool check(int v,int ord,int c){
	color[v]=c;
	for(int i=0;i<G[v].size();i++){
		int nv=G[v][i];
		if(ord!=cmp[nv])continue;
		if(c==color[nv])return false;
		if(color[nv]==0 && !check(nv,ord,-c))return false;
	}
	for(int i=0;i<rG[v].size();i++){
		int nv=rG[v][i];
		if(ord!=cmp[nv])continue;
		if(c==color[nv])return false;
		if(color[nv]==0 && !check(nv,ord,-c))return false;
	}
	return true;
}

int main(void){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++){
		scanf("%d",&c[i]);
	}
	for(int i=0;i<m;i++){
		scanf("%d%d",&f[i],&t[i]);
		G[f[i]].push_back(t[i]);
		rG[t[i]].push_back(f[i]);
	}
	int k=scc();
	for(int i=0;i<n;i++){
		if(color[i]==0 && !notbi[cmp[i]]){
			if(!check(i,cmp[i],1)){
				notbi[cmp[i]]=true;
			}
		}
	}
	for(int i=0;i<m;i++){
		int sf=cmp[f[i]];
		int st=cmp[t[i]];
		if(sf==st)continue;
		sccG[sf].push_back(PP(st,P(f[i],t[i])));
	}
	for(int i=0;i<k;i++){
		if(notbi[i]){
			int s=0;
			for(int j=0;j<lis[i].size();j++){
				s+=c[lis[i][j]];
			}
			sum[i][0]=s;
			sum[i][1]=s;
		}else{
			for(int j=0;j<lis[i].size();j++){
				if(color[lis[i][j]]==1)sum[i][0]+=c[lis[i][j]];
				else sum[i][1]+=c[lis[i][j]];
			}
		}
	}
	memset(dp,-1,sizeof(dp));
	dp[cmp[0]][0][0]=0;
	int res=0;
	for(int i=0;i<k;i++){
		for(int j=0;j<2;j++){
			for(int l=0;l<2;l++){
				if(dp[i][j][l]>=0){
					if(notbi[i]){
						dp[i][j][l]+=sum[i][0];
					}else{
						dp[i][j][l]+=sum[i][(j+l)%2];
					}
					res=max(dp[i][j][l],res);
					//printf("%d %d %d %d\n",i,j,l,dp[i][j][l]);
					for(int a=0;a<sccG[i].size();a++){
						int nv=sccG[i][a].first;
						int nf=sccG[i][a].second.first;
						int nt=sccG[i][a].second.second;
						int ncol=0;
						if(color[nt]==-1)ncol=1;
						int pcol=0;
						if(color[nf]==-1)pcol=1;
						if(notbi[i]){
							dp[nv][ncol][0]=max(dp[nv][ncol][0],dp[i][j][l]);
							dp[nv][ncol][1]=max(dp[nv][ncol][1],dp[i][j][l]);
						}else{
							int nn=1-l;
							int n2=abs(pcol-j);
							nn=(nn+n2)%2;
							dp[nv][ncol][nn]=max(dp[nv][ncol][nn],dp[i][j][l]);
						}
					}
				}
			}
		}
	}
	printf("%d\n",res);
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 32676
final_rank: 3

code_snippet: #include<bits/stdc++.h>

using namespace std;

const int MAX_N = 100000;

int N, M;
int C[MAX_N];
vector< int > g[MAX_N], r[MAX_N];

bool v[MAX_N], bipartite[MAX_N];
int comp[MAX_N], sum[2][MAX_N], cc[MAX_N];
vector< int > order;
vector< int > decomp[MAX_N];

int dp[2][MAX_N];

void dfs(int idx)
{
  if(v[idx]) return;
  v[idx] = true;
  for(auto &to : g[idx]) dfs(to);
  order.push_back(idx);
}

void rdfs(int idx, int ptr)
{
  if(~comp[idx]) return;
  comp[idx] = ptr;
  decomp[ptr].push_back(idx);
  for(auto &to : r[idx]) rdfs(to, ptr);
}

bool dfs2(int idx, bool color, int ptr)
{
  if(~cc[idx]) return (cc[idx] != color);
  cc[idx] = color;
  sum[color][ptr] += C[idx];
  bool flag = false;
  for(auto &to : g[idx]) {
    if(comp[to] == comp[idx]) flag |= dfs2(to, !color, ptr);
  }
  return (flag);
}

int main()
{
  scanf("%d %d", &N, &M);
  for(int i = 0; i < N; i++) {
    scanf("%d", &C[i]);
  }
  for(int i = 0; i < M; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    g[a].push_back(b);
    r[b].push_back(a);
  }

  for(int i = 0; i < N; i++) dfs(i);
  reverse(begin(order), end(order));
  int ptr = 0;
  memset(comp, -1, sizeof(comp));
  for(auto &u : order) {
    if(comp[u] == -1) rdfs(u, ptr++);
  }

  memset(cc, -1, sizeof(cc));
  for(int i = 0; i < ptr; i++) {
    bipartite[i] = dfs2(decomp[i][0], false, i);
  }
  
  memset(dp, -1, sizeof(dp));
  dp[cc[0]][comp[0]] = sum[cc[0]][comp[0]];

  int ret = 0;
  for(int i = 0; i < ptr; i++) {

    if(bipartite[i]) {
      if(dp[0][i] == -1 && dp[1][i] == -1) continue;
      int beet = 0;
      if(~dp[0][i]) beet = max(beet, dp[0][i] + sum[1][i]);
      if(~dp[1][i]) beet = max(beet, dp[1][i] + sum[0][i]);
      dp[0][i] = dp[1][i] = beet;
    }

    for(auto &curr : decomp[i]) {
      for(int j = 0; j < 2; j++) {
        if(dp[j][i] == -1) continue;
        for(auto &next : g[curr]) {
          if(comp[curr] == comp[next]) continue;
          int real = cc[curr] ^cc[next] ^j ^1;
          dp[real][comp[next]] = max(dp[real][comp[next]], dp[j][i] + sum[real][comp[next]]);
        }
      }
    }

    ret = max(ret, dp[0][i]);
    ret = max(ret, dp[1][i]);
  }

  printf("%d\n", ret);
}
accuracy: 1
time_ms: 50
memory_kb: 27072
final_rank: 2

code_snippet: #include<bits/stdc++.h>

using namespace std;

const int MAX_N = 100000;

int N, M;
int C[MAX_N];
vector< int > g[MAX_N], r[MAX_N];

bool v[MAX_N], bipartite[MAX_N];
int comp[MAX_N], sum[2][MAX_N], cc[MAX_N];
vector< int > order;
vector< int > decomp[MAX_N];

int dp[2][MAX_N];

void dfs(int idx)
{
  if(v[idx]) return;
  v[idx] = true;
  for(auto &to : g[idx]) dfs(to);
  order.push_back(idx);
}

void rdfs(int idx, int ptr)
{
  if(~comp[idx]) return;
  comp[idx] = ptr;
  decomp[ptr].push_back(idx);
  for(auto &to : r[idx]) rdfs(to, ptr);
}

bool dfs2(int idx, bool color, int ptr)
{
  if(~cc[idx]) return (cc[idx] != color);
  cc[idx] = color;
  sum[color][ptr] += C[idx];
  bool flag = false;
  for(auto &to : g[idx]) {
    if(comp[to] == comp[idx]) flag |= dfs2(to, !color, ptr);
  }
  return (flag);
}

int main()
{
  scanf("%d %d", &N, &M);
  for(int i = 0; i < N; i++) {
    scanf("%d", &C[i]);
  }
  for(int i = 0; i < M; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    g[a].push_back(b);
    r[b].push_back(a);
  }

  for(int i = 0; i < N; i++) dfs(i);
  reverse(begin(order), end(order));
  int ptr = 0;
  memset(comp, -1, sizeof(comp));
  for(auto &u : order) {
    if(comp[u] == -1) rdfs(u, ptr++);
  }

  memset(cc, -1, sizeof(v));
  for(int i = 0; i < ptr; i++) {
    bipartite[i] = dfs2(decomp[i][0], false, i);
  }
  for(int i = 0; i < N; i++) {
    assert(cc[i] >= 0);
  }

  memset(dp, -1, sizeof(dp));
  dp[cc[0]][comp[0]] = sum[cc[0]][comp[0]];

  int ret = 0;
  for(int i = 0; i < ptr; i++) {

    if(bipartite[i]) {
      if(dp[0][i] == -1 && dp[1][i] == -1) continue;
      int beet = 0;
      if(~dp[0][i]) beet = max(beet, dp[0][i] + sum[1][i]);
      if(~dp[1][i]) beet = max(beet, dp[1][i] + sum[0][i]);
      dp[0][i] = dp[1][i] = beet;
    }

    for(auto &curr : decomp[i]) {
      for(int j = 0; j < 2; j++) {
        if(dp[j][i] == -1) continue;
        for(auto &next : g[curr]) {
          if(comp[curr] == comp[next]) continue;
          if(cc[curr] == -1 || cc[next] == -1) continue;
          int real = cc[curr] ^cc[next] ^j ^1;
          dp[real][comp[next]] = max(dp[real][comp[next]], dp[j][i] + sum[real][comp[next]]);
        }
      }
    }

    ret = max(ret, dp[0][i]);
    ret = max(ret, dp[1][i]);
  }

  printf("%d\n", ret);
}
accuracy: 0.325
time_ms: 10
memory_kb: 15580
final_rank: 13

code_snippet: #include<bits/stdc++.h>

using namespace std;

const int MAX_N = 100000;

int N, M;
int C[MAX_N];
vector< int > g[MAX_N], r[MAX_N];

bool v[MAX_N], bipartite[MAX_N];
int comp[MAX_N], sum[2][MAX_N], cc[MAX_N];
vector< int > order;
vector< int > decomp[MAX_N];

int dp[2][MAX_N];

void dfs(int idx)
{
  if(v[idx]) return;
  v[idx] = true;
  for(auto &to : g[idx]) dfs(to);
  order.push_back(idx);
}

void rdfs(int idx, int ptr)
{
  if(~comp[idx]) return;
  comp[idx] = ptr;
  decomp[ptr].push_back(idx);
  for(auto &to : r[idx]) rdfs(to, ptr);
}

bool dfs2(int idx, bool color, int ptr)
{
  if(~cc[idx]) return (cc[idx] != color);
  cc[idx] = color;
  sum[color][ptr] += C[idx];
  bool flag = false;
  for(auto &to : g[idx]) {
    if(comp[to] == comp[idx]) flag |= dfs2(to, !color, ptr);
  }
  return (flag);
}

int main()
{
  scanf("%d %d", &N, &M);
  for(int i = 0; i < N; i++) {
    scanf("%d", &C[i]);
  }
  for(int i = 0; i < M; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    g[a].push_back(b);
    r[b].push_back(a);
  }

  for(int i = 0; i < N; i++) dfs(i);
  reverse(begin(order), end(order));
  int ptr = 0;
  memset(comp, -1, sizeof(comp));
  for(auto &u : order) {
    if(comp[u] == -1) rdfs(u, ptr++);
  }

  memset(cc, -1, sizeof(v));
  for(int i = 0; i < ptr; i++) {
    bipartite[i] = dfs2(decomp[i][0], false, i);
  }
  for(int i = 0; i < N; i++) {
    assert(cc[i] >= 0);
  }

  memset(dp, -1, sizeof(dp));
  dp[cc[0]][comp[0]] = sum[cc[0]][comp[0]];

  int ret = 0;
  for(int i = 0; i < ptr; i++) {

    if(bipartite[i]) {
      if(dp[0][i] == -1 && dp[1][i] == -1) continue;
      int beet = 0;
      if(~dp[0][i]) beet = max(beet, dp[0][i] + sum[1][i]);
      if(~dp[1][i]) beet = max(beet, dp[1][i] + sum[0][i]);
      dp[0][i] = dp[1][i] = beet;
    }

    for(auto &curr : decomp[i]) {
      for(int j = 0; j < 2; j++) {
        if(dp[j][i] == -1) continue;
        for(auto &next : g[curr]) {
          if(comp[curr] == comp[next]) continue;
          int real = cc[curr] ^cc[next] ^j ^1;
          dp[real][comp[next]] = max(dp[real][comp[next]], dp[j][i] + sum[real][comp[next]]);
        }
      }
    }

    ret = max(ret, dp[0][i]);
    ret = max(ret, dp[1][i]);
  }

  printf("%d\n", ret);
}
accuracy: 0.325
time_ms: 10
memory_kb: 15544
final_rank: 12

code_snippet: #include<bits/stdc++.h>

using namespace std;

const int MAX_N = 100000;

int N, M;
int C[MAX_N];
vector< int > g[MAX_N], r[MAX_N];

bool v[MAX_N], bipartite[MAX_N];
int comp[MAX_N], sum[2][MAX_N], cc[MAX_N];
vector< int > order;
vector< int > decomp[MAX_N];

int dp[2][MAX_N];

void dfs(int idx)
{
  if(v[idx]) return;
  v[idx] = true;
  for(auto &to : g[idx]) dfs(to);
  order.push_back(idx);
}

void rdfs(int idx, int ptr)
{
  if(~comp[idx]) return;
  comp[idx] = ptr;
  decomp[ptr].push_back(idx);
  for(auto &to : r[idx]) rdfs(to, ptr);
}

bool dfs2(int idx, bool color, int ptr)
{
  if(~cc[idx]) return (cc[idx] != color);
  cc[idx] = color;
  sum[color][ptr] += C[idx];
  bool flag = false;
  for(auto &to : g[idx]) {
    if(comp[to] == comp[idx]) flag |= dfs2(to, !color, ptr);
  }
  return (flag);
}

int main()
{
  scanf("%d %d", &N, &M);
  for(int i = 0; i < N; i++) {
    scanf("%d", &C[i]);
  }
  for(int i = 0; i < M; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    g[a].push_back(b);
    r[b].push_back(a);
  }

  for(int i = 0; i < N; i++) dfs(i);
  reverse(begin(order), end(order));
  int ptr = 0;
  memset(comp, -1, sizeof(comp));
  for(auto &u : order) {
    if(comp[u] == -1) rdfs(u, ptr++);
  }

  memset(cc, -1, sizeof(v));
  for(int i = 0; i < ptr; i++) {
    bipartite[i] = dfs2(decomp[i][0], false, i);
  }

  memset(dp, -1, sizeof(dp));
  dp[cc[0]][comp[0]] = sum[cc[0]][comp[0]];

  int ret = 0;
  for(int i = 0; i < ptr; i++) {

    if(bipartite[i]) {
      if(dp[0][i] == -1 && dp[1][i] == -1) continue;
      int beet = 0;
      if(~dp[0][i]) beet = max(beet, dp[0][i] + sum[1][i]);
      if(~dp[1][i]) beet = max(beet, dp[1][i] + sum[0][i]);
      dp[0][i] = dp[1][i] = beet;
    }

    for(auto &curr : decomp[i]) {
      for(int j = 0; j < 2; j++) {
        if(dp[j][i] == -1) continue;
        for(auto &next : g[curr]) {
          if(comp[curr] == comp[next]) continue;
          if(cc[curr] == -1 || cc[next] == -1) {
            continue;
          }
          int real = cc[curr] ^cc[next] ^j ^1;
          dp[real][comp[next]] = max(dp[real][comp[next]], dp[j][i] + sum[real][comp[next]]);
        }
      }
    }

    ret = max(ret, dp[0][i]);
    ret = max(ret, dp[1][i]);
  }

  printf("%d\n", ret);
}
accuracy: 0.325
time_ms: 30
memory_kb: 15580
final_rank: 19

code_snippet: #include<bits/stdc++.h>

using namespace std;

const int MAX_N = 100000;

int N, M;
int C[MAX_N];
vector< int > g[MAX_N], r[MAX_N];

bool v[MAX_N], bipartite[MAX_N];
int comp[MAX_N], sum[2][MAX_N], cc[MAX_N];
vector< int > order;
vector< int > decomp[MAX_N];

int dp[2][MAX_N];

void dfs(int idx)
{
  if(v[idx]) return;
  v[idx] = true;
  for(auto &to : g[idx]) dfs(to);
  order.push_back(idx);
}

void rdfs(int idx, int ptr)
{
  if(~comp[idx]) return;
  comp[idx] = ptr;
  decomp[ptr].push_back(idx);
  for(auto &to : r[idx]) rdfs(to, ptr);
}

bool dfs2(int idx, bool color, int ptr)
{
  if(~cc[idx]) return (cc[idx] != color);
  cc[idx] = color;
  sum[color][ptr] += C[idx];
  bool flag = false;
  for(auto &to : g[idx]) {
    if(comp[to] == comp[idx]) flag |= dfs2(to, !color, ptr);
  }
  return (flag);
}

int main()
{
  scanf("%d %d", &N, &M);
  for(int i = 0; i < N; i++) {
    scanf("%d", &C[i]);
  }
  for(int i = 0; i < M; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    g[a].push_back(b);
    r[b].push_back(a);
  }

  for(int i = 0; i < N; i++) dfs(i);
  reverse(begin(order), end(order));
  int ptr = 0;
  memset(comp, -1, sizeof(comp));
  for(auto &u : order) {
    if(comp[u] == -1) rdfs(u, ptr++);
  }

  memset(cc, -1, sizeof(v));
  for(int i = 0; i < ptr; i++) {
    bipartite[i] = dfs2(decomp[i][0], false, i);
  }

  memset(dp, -1, sizeof(dp));
  dp[cc[0]][comp[0]] = sum[cc[0]][comp[0]];

  int ret = 0;
  for(int i = 0; i < ptr; i++) {

    if(bipartite[i]) {
      if(dp[0][i] == -1 && dp[1][i] == -1) continue;
      int beet = 0;
      if(~dp[0][i]) beet = max(beet, dp[0][i] + sum[1][i]);
      if(~dp[1][i]) beet = max(beet, dp[1][i] + sum[0][i]);
      dp[0][i] = dp[1][i] = beet;
    }

    for(auto &curr : decomp[i]) {
      for(int j = 0; j < 2; j++) {
        if(dp[j][i] == -1) continue;
        for(auto &next : g[curr]) {
          if(comp[curr] == comp[next]) continue;
          if(comp[curr] == -1 || comp[next] == -1) {
            continue;
          }
          int real = cc[curr] ^cc[next] ^j ^1;
          dp[real][comp[next]] = max(dp[real][comp[next]], dp[j][i] + sum[real][comp[next]]);
        }
      }
    }

    ret = max(ret, dp[0][i]);
    ret = max(ret, dp[1][i]);
  }

  printf("%d\n", ret);
}
accuracy: 0.325
time_ms: 30
memory_kb: 15508
final_rank: 17

code_snippet: #include<bits/stdc++.h>

using namespace std;

const int MAX_N = 100000;

int N, M;
int C[MAX_N];
vector< int > g[MAX_N], r[MAX_N];

bool v[MAX_N], bipartite[MAX_N];
int comp[MAX_N], sum[2][MAX_N], cc[MAX_N];
vector< int > order;
vector< int > decomp[MAX_N];

int dp[2][MAX_N];

void dfs(int idx)
{
  if(v[idx]) return;
  v[idx] = true;
  for(auto &to : g[idx]) dfs(to);
  order.push_back(idx);
}

void rdfs(int idx, int ptr)
{
  if(~comp[idx]) return;
  comp[idx] = ptr;
  decomp[ptr].push_back(idx);
  for(auto &to : r[idx]) rdfs(to, ptr);
}

bool dfs2(int idx, bool color, int ptr)
{
  if(~cc[idx]) return (cc[idx] != color);
  cc[idx] = color;
  sum[color][ptr] += C[idx];
  bool flag = false;
  for(auto &to : g[idx]) {
    if(comp[to] == comp[idx]) flag |= dfs2(to, !color, ptr);
  }
  return (flag);
}

int main()
{
  scanf("%d %d", &N, &M);
  for(int i = 0; i < N; i++) {
    scanf("%d", &C[i]);
  }
  for(int i = 0; i < M; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    g[a].push_back(b);
    r[b].push_back(a);
  }

  for(int i = 0; i < N; i++) dfs(i);
  reverse(begin(order), end(order));
  int ptr = 0;
  memset(comp, -1, sizeof(comp));
  for(auto &u : order) {
    if(comp[u] == -1) rdfs(u, ptr++);
  }

  memset(cc, -1, sizeof(v));
  for(int i = 0; i < ptr; i++) {
    bipartite[i] = dfs2(decomp[i][0], false, i);
  }

  memset(dp, -1, sizeof(dp));
  dp[cc[0]][comp[0]] = sum[cc[0]][comp[0]];

  int ret = 0;
  for(int i = 0; i < ptr; i++) {

    if(bipartite[i]) {
      if(dp[0][i] == -1 && dp[1][i] == -1) continue;
      int beet = 0;
      if(~dp[0][i]) beet = max(beet, dp[0][i] + sum[1][i]);
      if(~dp[1][i]) beet = max(beet, dp[1][i] + sum[0][i]);
      dp[0][i] = dp[1][i] = beet;
    }

    for(auto &curr : decomp[i]) {
      for(int j = 0; j < 2; j++) {
        if(dp[j][i] == -1) continue;
        for(auto &next : g[curr]) {
          if(comp[curr] == comp[next]) continue;
          int real = cc[curr] ^cc[next] ^j ^1;
          dp[real][comp[next]] = max(dp[real][comp[next]], dp[j][i] + sum[real][comp[next]]);
        }
      }
    }

    ret = max(ret, dp[0][i]);
    ret = max(ret, dp[1][i]);
  }

  printf("%d\n", ret);
}
accuracy: 0.325
time_ms: 30
memory_kb: 15556
final_rank: 18

code_snippet: #include<bits/stdc++.h>

using namespace std;

const int MAX_N = 100000;

int N, M;
int C[MAX_N];
vector< int > g[MAX_N], r[MAX_N];

bool v[MAX_N], bipartite[MAX_N];
int comp[MAX_N], sum[2][MAX_N], cc[MAX_N];
vector< int > order;
vector< int > decomp[MAX_N];

int dp[2][MAX_N];

void dfs(int idx)
{
  if(v[idx]) return;
  v[idx] = true;
  for(auto &to : g[idx]) dfs(to);
  order.push_back(idx);
}

void rdfs(int idx, int ptr)
{
  if(~comp[idx]) return;
  comp[idx] = ptr;
  decomp[ptr].push_back(idx);
  for(auto &to : r[idx]) rdfs(to, ptr);
}

bool dfs2(int idx, bool color, int ptr)
{
  if(~cc[idx]) return (cc[idx] != color);
  cc[idx] = color;
  sum[color][ptr] += C[idx];
  bool flag = false;
  for(auto &to : g[idx]) {
    if(comp[to] == comp[idx]) flag |= dfs2(to, !color, ptr);
  }
  return (flag);
}

int main()
{
  scanf("%d %d", &N, &M);
  for(int i = 0; i < N; i++) {
    scanf("%d", &C[i]);
  }
  for(int i = 0; i < M; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    g[a].push_back(b);
    r[b].push_back(a);
  }

  dfs(0);
  reverse(begin(order), end(order));
  int ptr = 0;
  memset(comp, -1, sizeof(comp));
  for(auto &u : order) {
    if(comp[u] == -1) rdfs(u, ptr++);
  }

  memset(cc, -1, sizeof(v));
  for(int i = 0; i < ptr; i++) {
    bipartite[i] = dfs2(decomp[i][0], false, i);
  }

  memset(dp, -1, sizeof(dp));
  dp[cc[0]][comp[0]] = sum[cc[0]][comp[0]];

  int ret = 0;
  for(int i = 0; i < ptr; i++) {

    if(bipartite[i]) {
      int fact = max(dp[0][i] + sum[1][i], dp[1][i] + sum[0][i]);
      dp[0][i] = dp[1][i] = fact;
    }

    for(auto &curr : decomp[i]) {
      for(int j = 0; j < 2; j++) {
        if(dp[j][i] == -1) continue;
        for(auto &next : g[curr]) {
          if(comp[curr] == comp[next]) continue;
          if(cc[curr] == -1 || cc[next] == -1) {
            continue;
          }
          int real = cc[curr] ^cc[next] ^j ^1;
          dp[real][comp[next]] = max(dp[real][comp[next]], dp[j][i] + sum[real][comp[next]]);
        }
      }
    }

    ret = max(ret, dp[0][i]);
    ret = max(ret, dp[1][i]);
  }

  printf("%d\n", ret);
}
accuracy: 0.325
time_ms: 30
memory_kb: 14540
final_rank: 15

code_snippet: #include<bits/stdc++.h>

using namespace std;

const int MAX_N = 100000;

int N, M;
int C[MAX_N];
vector< int > g[MAX_N], r[MAX_N];

bool v[MAX_N], bipartite[MAX_N];
int comp[MAX_N], sum[2][MAX_N], cc[MAX_N];
vector< int > order;
vector< int > decomp[MAX_N];

int dp[2][MAX_N];

void dfs(int idx)
{
  if(v[idx]) return;
  v[idx] = true;
  for(auto &to : g[idx]) dfs(to);
  order.push_back(idx);
}

void rdfs(int idx, int ptr)
{
  if(~comp[idx]) return;
  comp[idx] = ptr;
  decomp[ptr].push_back(idx);
  for(auto &to : r[idx]) rdfs(to, ptr);
}

bool bfs(int idx, int ptr)
{
  queue< int > que;
  que.emplace(idx);
  cc[idx] = 0;
  sum[0][ptr] += C[idx];

  bool flag = false;
  while(!que.empty()) {
    int p = que.front();
    que.pop();
    for(auto &to : g[p]) {
      if(comp[to] == comp[p]) {
        if(~cc[to]) {
          if(cc[to] == cc[p]) flag = true;
        } else {
          cc[to] = 1 - cc[p];
          sum[cc[to]][ptr] += C[to];
          que.push(to);
        }
      }
    }
  }
  return (flag);
}

int main()
{
  scanf("%d %d", &N, &M);

  for(int i = 0; i < N; i++) {
    scanf("%d", &C[i]);
  }
  for(int i = 0; i < M; i++) {
    int a, b;
    scanf("%d %d", &a, &b);
    g[a].push_back(b);
    r[b].push_back(a);
  }

  dfs(0);
  reverse(begin(order), end(order));
  int ptr = 0;
  memset(comp, -1, sizeof(comp));
  for(auto &u : order) {
    if(comp[u] == -1) rdfs(u, ptr++);
  }

  memset(cc, -1, sizeof(v));
  for(int i = 0; i < ptr; i++) {
    bipartite[i] = bfs(decomp[i][0], i);
  }

  memset(dp, -1, sizeof(dp));
  dp[cc[0]][comp[0]] = sum[cc[0]][comp[0]];

  int ret = 0;

  for(int i = 0; i < ptr; i++) {
    if(bipartite[i]) {
      int fact = max(dp[0][i] + sum[1][i], dp[1][i] + sum[0][i]);
      dp[0][i] = dp[1][i] = fact;
    }

    for(auto &curr : decomp[i]) {
      for(int j = 0; j < 2; j++) {
        if(dp[j][i] == -1) continue;
        for(auto &next : g[curr]) {
          if(comp[curr] == comp[next]) continue;
          if(cc[curr] == -1 || cc[next] == -1) {
            // throw (0);
            continue;

          } // ee...
          int real = cc[curr] ^cc[next] ^j ^1;
          dp[real][comp[next]] = max(dp[real][comp[next]], dp[j][i] + sum[real][comp[next]]);
        }
      }
    }

    ret = max(ret, dp[0][i]);
    ret = max(ret, dp[1][i]);
  }

  printf("%d\n", ret);
}
accuracy: 0.325
time_ms: 30
memory_kb: 14684
final_rank: 16