POJ 3160 Father Christmas flymouse 强联通

来源:互联网 发布:linux倒序 ll 编辑:程序博客网 时间:2024/04/30 11:54

说实话,真心没看懂题目是什么意思,在搜了一下后终于搞懂了,就是给一个无向图,每个点有一个权(可为负),让你仍选一条路径走,去访问别的点,到达该点的时候可以选择得到权或者放弃,求使得获得的权最大的值 ;赶脚有一点树形DP在里面;

思路:强联通求缩点,并把每个缩点出发的最大值求出来,最大的节点即为所求;

#include <iostream>#include <cstdio>#include <cstring>#include <vector>using namespace std ;const int N = 30000 + 11 ;const int M = 150000 + 11 ;struct Greaph {struct Edge {int e ;int next ;};Edge err[M] ; int head[N] ; int idx ;int instack[N] ; int dfn[N] ; int low[N] ; int visit_time ; int color ;vector<int> stk ;vector<int> arr[N] ;int power[N] ; int right[N] ;int maxn  ;int n , m ;void addinfo() {int a , b ;for(int i = 1 ; i <= n ; ++i) {arr[i].clear() ;scanf("%d" ,power+i) ;if(power[i] < 0) power[i] = 0 ;}while(m--) {scanf("%d%d" ,&a ,&b ) ;err[idx].e = b+1 ;err[idx].next = head[a+1] ;head[a+1] = idx++ ;}}void init() {memset(head , -1 , sizeof(head)) ;memset(instack , 0 , sizeof(instack)) ;visit_time = 0 , color = 2 , idx = 1 ;stk.clear() ;maxn = 0 ;}void dfs(int u) {stk.push_back(u) ;instack[u] = 1 ;dfn[u] = low[u] = ++visit_time ;for(int i = head[u] ; i != -1 ; i = err[i].next) {int e = err[i].e ;if(instack[e] == 0) {dfs(e) ;low[u] = min(low[u] , low[e]) ;}else if(instack[e] == 1) {low[u] = min(low[u] , dfn[e]) ;}if(instack[e] > 1) {arr[u].push_back(instack[e]) ;}}if(low[u] == dfn[u]) {right[color] = 0 ;int maxl = 0 , tmp ;while(stk.back() != u) {tmp = stk.back() ;stk.pop_back() ;right[color] += power[tmp] ;instack[tmp] = color ;for(int j = 0 ; j < arr[tmp].size() ; ++j) {maxl = max(maxl , right[arr[tmp][j]]) ;}}stk.pop_back() ;for(int j = 0 ; j < arr[u].size() ;++j) {maxl = max( maxl , right[arr[u][j]]) ;}right[color] += (power[u] + maxl) ;maxn = max(maxn , right[color]) ;instack[u] = color++ ;}}void std_fun() {init() ;addinfo() ;for(int i = 1 ; i <= n ; ++i) {if(instack[i] == 0) dfs(i) ;}printf("%d\n" , maxn) ;}}g ;int main() {//freopen("data.in" , "r" , stdin) ;while(scanf("%d%d" ,&g.n ,&g.m)==2) {g.std_fun() ;}}


0 0
原创粉丝点击