洛谷 P4742 【[Wind Festival]Running In The Sky】

tarjan模板题


这道题tarjan加记忆化搜索就行,记忆化搜索中,就可以完美解决最大值和最长路。直接讲比较抽象,上代码:

#include <bits/stdc++.h>
using namespace std;
int n , m , now , tot , ans1 , ans2;
int dfn[200010] , low[200010] , home[200010] , a[200010] , dis[200010] , vis[200010] , kp[200010];
int f[200010] , maxx[200010];
stack<int> s;
vector<int> e[200010];
vector<int> ne[200010];	//存重建的图 
void tarjan(int x){
	dfn[x] = low[x] = ++now;
	s.push(x);
	vis[x] = 1;
	for(int i = 0; i < e[x].size(); i++){
		int nx = e[x][i];
		if(!dfn[nx]){
			tarjan(nx);
			low[x] = min(low[x] , low[nx]);
		}else if(vis[nx]) low[x] = min(low[x] , dfn[nx]); 
	}
	if(dfn[x] == low[x]){
		tot++;
		while(!s.empty()){
			int top = s.top();
			s.pop();
			kp[tot] = max(kp[tot] , a[top]);	//统计下最大值 
			vis[top] = 0;
			dis[tot] += a[top];	//统计点的和 
			home[top] = tot;
			if(top == x) break;
		}
	}
}
void dfs(int x){
	if(f[x]) return;
	f[x] = dis[x];
	int ans = 0 , ansmax = 0;
	for(int i = 0; i < ne[x].size(); i++){
		int nx = ne[x][i];
		dfs(nx);
		if(f[nx] > ans){	//最长路优先,其次最大值 
			ans = f[nx];
			ansmax = maxx[nx];
		}else if(f[nx] == ans){
			if(maxx[nx] > ansmax) ansmax = maxx[nx];
		}
	}
	f[x] += ans;	//选择最长路 
	maxx[x] = max(ansmax , kp[x]);
}
int main(){
	cin >> n >> m;
	for(int i = 1; i <= n; i++) cin >> a[i];
	for(int i = 1; i <= m; i++){
		int x , y;
		cin >> x >> y;
		e[x].push_back(y);
	}
	for(int i = 1; i <= n; i++)
		if(!dfn[i]) tarjan(i);
	for(int i = 1; i <= n; i++)
		for(int j = 0; j < e[i].size(); j++){	//重建 
			int nx = e[i][j];
			if(home[nx] != home[i]) ne[home[i]].push_back(home[nx]);
		}
	for(int i = 1; i <= tot; i++) dfs(i);	//记忆化搜索 
	for(int i = 1; i <= tot; i++)	//枚举答案 
		if(f[i] > ans1){
			ans1 = f[i];
			ans2 = maxx[i];
		}else if(f[i] == ans1){
			if(maxx[i] > ans2) ans2 = maxx[i];
		}
	cout << ans1 << " " << ans2;
	return 0;
}
posted @ 2020-09-19 17:33  草鱼泡酒  阅读(131)  评论(0编辑  收藏  举报