题意:
      给你一个有向图,每个点上有一个权值,可正可负,然后给你一些链接关系,让你找到一个起点,从起点开始走,走过的边可以在走,但是拿过权值的点就不能再拿了,问最多能拿到多少权值?

思路:
      首先我们考虑一个简单的问题,这个题目的负权值点肯定不拿,对于一个环(应该说是一个强连通分量)来说要拿可以一下全拿走(这个自己黄画画),那么一个环的价值是多少?就是这个强连通分量里所有正权值的和,这样我们一边强连通缩点,缩点之后变成了一个无环的有向图,然后在在上面跑最长路就行了,还有提醒一点,题目说的起点不固定,这个也好处理,我们只要在虚拟出来一个起点,到所有点的权值都是0就行了,这样就能一遍spfa搞定了,千万别跑n遍spfa那样太无脑了。

虽然简单,但感觉这个题目还不错,挺有实际意义的。

#include<stack>
#include<queue>
#include<stdio.h>
#include<string.h>

#define N_node 30000 + 10
#define N_edge 200000 + 50
#define INF 1000000000

using namespace std;

typedef struct
{
    int to ,cost ,next;
}STAR;

typedef struct
{
    int a ,b;
}EDGE;

EDGE E[N_edge];
STAR E1[N_edge] ,E2[N_edge];
int list1[N_node] ,list2[N_node] ,tot;
int Belong[N_node] ,mark[N_node] ,cont;
int s_x[N_node] ,get[N_node] ,cost[N_node];
stack<int>sk;

void add(int a ,int b ,int c)
{
    E1[++tot].to = b;
    E1[tot].cost = c;
    E1[tot].next = list1[a];
    list1[a] = tot;

E2[tot].to = a;
    E2[tot].cost = c;
    E2[tot].next = list2[b];
    list2[b] = tot;
}

void DFS1(int s)
{
    mark[s] = 1;
    for(int k = list1[s] ;k ;k = E1[k].next)
    if(!mark[E1[k].to]) DFS1(E1[k].to);
    sk.push(s);
}

void DFS2(int s)
{
    mark[s] = 1;
    Belong[s] = cont;
    for(int k = list2[s] ;k ;k = E2[k].next)
    if(!mark[E2[k].to]) DFS2(E2[k].to);
}

void Spfa(int s ,int n)
{
    memset(mark ,0 ,sizeof(mark));
    for(int i = 0 ;i <= n ;i ++)
    s_x[i] = -INF;
    queue<int>q;
    q.push(s);
    mark[s] = 1;
    s_x[s] = 0;
    while(!q.empty())
    {
        int xin ,tou;
        tou = q.front();
        q.pop();
        mark[tou] = 0;
        for(int k = list1[tou] ;k ;k = E1[k].next)
        {
            xin = E1[k].to;
            if(s_x[xin] < s_x[tou] + E1[k].cost)
            {
                s_x[xin] = s_x[tou] + E1[k].cost;
                if(!mark[xin])
                {
                    mark[xin] = 1;
                    q.push(xin);
                }
            }
        }
    }
}

int main ()
{
    int n ,m ,i ,a ,b;
    while(~scanf("%d %d" ,&n ,&m))
    {
        for(i = 1 ;i <= n ;i ++)
        scanf("%d" ,&cost[i]);
        memset(list1 ,0 ,sizeof(list1));
        memset(list2 ,0 ,sizeof(list2));
        tot = 1;
        for(i = 1 ;i <= m ;i ++)
        {
            scanf("%d %d" ,&a ,&b);
            a ++ ,b ++;
            add(a ,b ,1);
            E[i].a = a ,E[i].b = b;
        }
        while(!sk.empty()) sk.pop();
        memset(mark ,0 ,sizeof(mark));
        for(i = 1 ;i <= n ;i ++)
        if(!mark[i]) DFS1(i);
        memset(mark ,0 ,sizeof(mark));
        cont = 0;
        while(!sk.empty())
        {
            int to = sk.top();
            sk.pop();
            if(mark[to]) continue;
            ++cont;
            DFS2(to);
        }
        memset(get ,0 ,sizeof(get));
        for(i = 1 ;i <= n ;i ++)
        if(cost[i] >= 0) get[Belong[i]] += cost[i];
        memset(list1 ,0 ,sizeof(list1));
        memset(list2 ,0 ,sizeof(list2));
        tot = 1;
        for(i = 1 ;i <= n ;i ++)
        add(0 ,i ,get[i]);
        for(i = 1 ;i <= m ;i ++)
        {
            a = Belong[E[i].a];
            b = Belong[E[i].b];
            if(a == b) continue;
            add(a ,b ,get[b]);
        }
        Spfa(0 ,n);
        int ans = 0;
        for(i = 1 ;i <= n ;i ++)
        if(ans < s_x[i]) ans = s_x[i];
        printf("%d\n" ,ans);

}
    return 0;
}

POJ3160强连通+spfa最长路(不错)相关推荐

  1. 洛谷 P3119 [USACO15JAN]草鉴定Grass Cownoisseur (SCC缩点,SPFA最长路,枚举反边)

    P3119 [USACO15JAN]草鉴定Grass Cownoisseur 题目描述 In an effort to better manage the grazing patterns of hi ...

  2. P1931 套利-SPFA最长路与环的判断

    题目连接套利 - 洛谷 制作不易,点赞走人 首先,每种货币看做一个点,map哈希赋值赋成若干个数字,货币之间转换关系看做两个节点之间的有向,注意是有向边,权值为比率,最长路的值就代表了兑换到该节点时的 ...

  3. *【HDU - 6201】transaction transaction transaction(树形dp 或 spfa最长路 或 网络流)

    题干: 题目大意: 给出一棵n个顶点的树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过所需要的花费.现在需要你在树上选择两个点,一个作为买入商品的点,一个作为卖出商品 ...

  4. codevs 1183 泥泞的道路 二分+SPFA最长路

    题目描述 Description CS有n个小区,并且任意小区之间都有两条单向道路(a到b,b到a)相连.因为最近下了很多暴雨,很多道路都被淹了,不同的道路泥泞程度不同.小A经过对近期天气和地形的科学 ...

  5. P1807 最长路 (SPFA写法)

    题目描述 设 G 为有 n 个顶点的带权有向无环图,G 中各顶点的编号为 1 到 n,请设计算法,计算图 G 中 1,n 间的最长路径. 输入格式 输入的第一行有两个整数,分别代表图的点数 n 和边数 ...

  6. The Largest Clique UVA - 11324( 强连通分量 + dp最长路)

    这题  我刚开始想的是  缩点后  求出入度和出度为0 的点  然后统计个数  用总个数 减去 然而 这样是不可以的  画个图就明白了... 如果  减去度为0的点  那么最后如果出现这样的情况是不可 ...

  7. BZOJ 2019 [Usaco2009 Nov]找工作:spfa【最长路】【判正环】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2019 题意: 奶牛们没钱了,正在找工作.农夫约翰知道后,希望奶牛们四处转转,碰碰运气. 而 ...

  8. 【SPFA】最长路(洛谷)

    最长路 题目 设G为有n个顶点的有向无环图,G中各顶点的编号为1到n,且当为G中的一条边时有i < j.设w(i,j)为边的长度,请设计算法,计算图G中<1,n>间的最长路径. 输入 ...

  9. 计蒜客——闯关游戏 SPFA找最长路

    问题描述 蒜头君在玩一个很好玩的游戏,这个游戏一共有至多 100 个地图,其中地图 1 是起点,房间 n 是终点.有的地图是补给站,可以加 ki点体力,而有的地图里存在怪物,需要消耗 ki 点体力,地 ...

最新文章

  1. 逻辑回归及常用模型分类评估方法
  2. SNMP功能开发简介 三 使用DEBUGMSG打印指定的信息
  3. 分享平时工作中那些给力的shell命令(更新版)
  4. 黄聪:WordPress 启用HTTPS设置(转)
  5. JAVA知识学习——类的修饰符
  6. Linux内核线程kernel thread详解--Linux进程的管理与调度
  7. redis修改端口号后还是占用6379_Redis分布式缓存分布式集群搭建
  8. 科学的分析猪八戒到底是什么猪,黑猪还是白猪?
  9. 库克跟乔布斯差几代iPhone? 解读iPhone十年变与不变
  10. 2017行进中的杂想,做一个极少数的历史
  11. css 选择器的应用
  12. sql2008r2服务器维护,Windows Server 2008 r2服务器上安装SQL Server 2008 r2的方法
  13. 基于labVIEW的学习(一)函数信号发生器
  14. 背阔肌(04):杠铃俯身划船
  15. 使用dd命令切割文件
  16. 小米打开或关闭MIUI9开发者选项
  17. Transformer如何用于视频?最新「视频Transformer」2022综述
  18. CF1364D Ehab‘s Last Corollary(思维,环,二分图,构造)
  19. 22届春季校招实习试水之路1(Java后端)
  20. c++项目 基于(多态,封装、继承类)——RPG小游戏 勇闯地下城

热门文章

  1. Apache activemq入门示例(maven项目)
  2. 《SolidWorks 2016中文版机械设计从入门到精通》——第1章 认识SolidWorks1.1 SolidWorks概述...
  3. lnmp、lamp、lnmpa一键安装包
  4. mysql 5.0 to mysql 5.1的BTREE索引问题
  5. 我看team work
  6. Mysql存储引擎MyIsAM和InnoDB区别
  7. IP分类以及特殊IP
  8. SQL Server 数据库状态选项
  9. jQueryui autocomplete使用示例
  10. 为什么程序员不擅长估算时间?