poj3207Ikki's Story IV - Panda's Trick tarjan缩点

//给一个有向图,每个点都有权值(可能有负权),从任意起点遍历一遍这个图,
//走每一点都可以选择得到和不得到这个权值,问最多能得到多少权值
//先用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

poj3207Ikki's Story IV - Panda's Trick tarjan缩点的相关文章

POJ3207-Ikki&#39;s Story IV - Panda&#39;s Trick(2-SAT)

Ikki's Story IV - Panda's Trick Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 7841   Accepted: 2900 Description liympanda, one of Ikki's friend, likes playing games with Ikki. Today after minesweeping with Ikki and winning so many tim

POJ-3207-Ikki&#39;s Story IV - Panda&#39;s Trick(2-sat模板)

2-sat模板提. 代码: #include<iostream> #include<cstdio> #include<cmath> #include<map> #include<queue> #include<vector> #include<cstring> #include<algorithm> #define rep(i,a,b) for(int i=(a);i<(b);i++) #define r

HDU 3207 Ikki&#39;s Story IV - Panda&#39;s Trick(图论-2SAT,图论-tarjan)

Ikki's Story IV - Panda's Trick Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 7821   Accepted: 2892 Description liympanda, one of Ikki's friend, likes playing games with Ikki. Today after minesweeping with Ikki and winning so many tim

POJ 3207 Ikki&#39;s Story IV - Panda&#39;s Trick

简单的看了2-sat……似乎还是挺神奇的东西……等大致刷完几道题再来写总结吧! 而这道题……算是2-sat的超级入门题了吧 不过题目大意也是醉了:圆上顺序排列n个点,现要在一些点间连边,规定边只能在圆内或圆外,求有没有可能不相交 .一开始想的是嗷嗷嗷,圆上两个点的连线怎么可能有什么在圆外在圆内之分,不都是弦么?后来才知道……原来两个点的连线不是直线可以使曲线…… 判定是否相交很简单吧……看成是一条直线上四个点,那么如果e1.a<e2.a<e1.b<e2.b就相交啦…… 都说是热身题没多难

poj3207 Ikki&#39;s Story IV - Panda&#39;s Trick

Description liympanda, one of Ikki’s friend, likes playing games with Ikki. Today after minesweeping with Ikki and winning so many times, he is tired of such easy games and wants to play another game with Ikki. liympanda has a magic circle and he put

POJ 3207 Ikki&#39;s Story IV - Panda&#39;s Trick (2-SAT)

题目地址:POJ 3207 找好矛盾关系,矛盾关系是(2,5)和(3,6)这两个只能一个在外边,一个在里边,利用这个矛盾关系来建图. 可以用在外边和里边来当1和0,最后判断每对是否出现矛盾. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #inc

POJ 3207 Ikki&#39;s Story IV - Panda&#39;s Trick(2 - sat啊)

题目链接:http://poj.org/problem?id=3207 Description liympanda, one of Ikki's friend, likes playing games with Ikki. Today after minesweeping with Ikki and winning so many times, he is tired of such easy games and wants to play another game with Ikki. liy

【POJ】3207 Ikki&#39;s Story IV - Panda&#39;s Trick

http://poj.org/problem?id=3207 题意:一个圆上顺时针依次排列着标号为1-n的点,这些点之间共有m条边相连,每两个点只能在圆内或者圆外连边.问是否存在这些边不相交的方案.(n<=1000, m<=500) #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <iostream> using n

[2-SAT] poj 3207 Ikki&#39;s Story IV - Panda&#39;s Trick

题目链接: http://poj.org/problem?id=3207 Ikki's Story IV - Panda's Trick Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 8063   Accepted: 2969 Description liympanda, one of Ikki's friend, likes playing games with Ikki. Today after minesweep