//给一个有向图,每个点都有权值(可能有负权),从任意起点遍历一遍这个图,
//走每一点都可以选择得到和不得到这个权值,问最多能得到多少权值
//先用tarjan进行缩点,得到一个森林,从这个森林的每棵树的根节点开始
//dfs搜一遍得到最大的一条路
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std ;
const int maxn = 150010 ;
int dfn[maxn],low[maxn],stack[maxn] , isstack[maxn] ;
int vis[maxn] ;int head[maxn] , a[maxn],w[maxn] ;
int step , num , top ,nedge;int ans ;
vector<int> vec[maxn] ;int n ,m ;int belong[maxn] ;
struct Edge
{
int v ;
int next ;
}edge[maxn];
void addedge(int u , int v)
{
edge[nedge].v = v ;
edge[nedge].next = head[u] ;
head[u] = nedge++ ;
}
void init()
{
memset(head , -1 , sizeof(head)) ;
memset(vis ,0 ,sizeof(vis)) ;
memset(dfn , 0 ,sizeof(dfn)) ;
memset(isstack , 0 ,sizeof(isstack)) ;
memset(w ,0 , sizeof(w)) ;
for(int i = 0 ;i <= n;i++)
vec[i].clear() ;
step = top = num = nedge = 0 ;
}
void tarjan(int u)
{
stack[++top] = u ;
isstack[u] = 1 ;
low[u] = dfn[u] = ++step ;
for(int i = head[u]; i!=-1; i = edge[i].next)
{
int v = edge[i].v ;
if(!dfn[v])
{
tarjan(v) ;
low[u] = min(low[u] , low[v]) ;
}
else if(isstack[v])
low[u] = min(low[u] , dfn[v]) ;
}
if(low[u] == dfn[u])
{
num++ ;
int v = 0 ;
while(u != v)
{
v = stack[top--] ;
isstack[v] = 0 ;
belong[v] = num ;
w[num] += max(a[v] , 0 ) ;
}
}
}
void build_tree()
{
for(int i = 1;i <= n;i++)
for(int j = head[i] ; j != -1 ; j =edge[j].next)
{
int u = belong[i] ;
int v = belong[edge[j].v] ;
if(u == v)continue ;
vec[u].push_back(v) ;
vis[v] = 1 ;
}
}
int dfs(int u)
{
int ma = 0 ;
for(int i = 0;i < vec[u].size() ;i++)
{
int v = vec[u][i] ;
ma = max(ma , dfs(v)) ;
}
return ma + w[u] ;
}
int main()
{
// freopen("in.txt" , "r" , stdin) ;
while(~scanf("%d%d" , &n , &m))
{
init() ;
for(int i = 1;i <= n;i++)
scanf("%d" , &a[i]) ;
while(m--)
{
int u , v ;
scanf("%d%d" , &u , &v) ;
addedge(u+1 , v+1) ;
}
for(int i = 1;i <= n;i++)
if(!dfn[i])
tarjan(i) ;
build_tree() ;
ans = 0 ;
for(int i = 1;i <= n;i++)
if(!vis[i])
ans = max(ans , dfs(i)) ;
printf("%d\n" , ans) ;
}
return 0 ;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
poj3207Ikki's Story IV - Panda's Trick tarjan缩点
时间: 2024-10-15 21:23:28