1179: [Apio2009]Atm

Time Limit: 15 Sec  Memory Limit: 162 MB
Submit: 3250  Solved: 1346
[Submit][Status][Discuss]

Description

Input

第一行包含两个整数N、M。N表示路口的个数,M表示道路条数。接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号。接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数。接下来一行包含两个整数S、P,S表示市中心的编号,也就是出发的路口。P表示酒吧数目。接下来的一行中有P个整数,表示P个有酒吧的路口的编号

Output

输出一个整数,表示Banditji从市中心开始到某个酒吧结束所能抢劫的最多的现金总数。

Sample Input

6 7
1 2
2 3
3 5
2 4
4 1
2 6
6 5
10
12
8
16
1 5
1 4
4
3
5
6

Sample Output

47

HINT

50%的输入保证N, M<=3000。所有的输入保证N, M<=500000。每个ATM机中可取的钱数为一个非负整数且不超过4000。输入数据保证你可以从市中心沿着Siruseri的单向的道路到达其中的至少一个酒吧。

 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<algorithm>
using namespace std;
#define N 500001
stack<int>Sta;
queue<int>Que;
vector<int>Gra[N],newGra[N];
bool isBar[N],inStack[N];
int low[N],dfn[N],belong[N],money[N],newMoney[N],cnt,Time,start;
int maxMoney[N];
void Tarjan(int s)
{
    dfn[s] = low[s] = ++Time;
    Sta.push(s);
    inStack[s] = true;
    for(int i=0;i<Gra[s].size();i++)
    {
        int j = Gra[s][i];
        if(dfn[j] == 0){
            Tarjan(j);
            low[s] = min(low[s], low[j]);
        }
        else if(inStack[j] == true){
            low[s] = min(low[s], dfn[j]);
        }
    }
    if(dfn[s] == low[s])
        {
            cnt ++;
            while(!Sta.empty()){
              int temp = Sta.top(); Sta.pop();
              belong[temp] = cnt;
              newMoney[cnt] += money[temp];
              inStack[temp] = false;
              if(temp == s) break;
            }
        }
}
 
int spfa()
{
    int ans = 0;
    Que.push(start);
    memset(maxMoney,0,sizeof(maxMoney));
    maxMoney[start] = newMoney[start];
    while(!Que.empty())
    {
        int now = Que.front(); Que.pop();
        for(int i = 0; i < newGra[now].size(); i++)
        {
            int j = newGra[now][i];
            if(maxMoney[now] + newMoney[j] > maxMoney[j])
            {
                maxMoney[j] = maxMoney[now] + newMoney[j];
                Que.push(j);
            }
            if(isBar[j]) ans = max(ans, maxMoney[j]);
        }
    }
    return ans;
}
 
int main()
{
    int n,m,a,b,s,p;
    scanf("%d%d",&n,&m);
    for (int i = 0; i < m; i++) {
      /* code */
      scanf("%d%d",&a, &b);
      Gra[a].push_back(b);
    }
    for (int i = 1; i <= n; i++) {
      /* code */
      scanf("%d",&money[i]);
    }
    scanf("%d%d",&s,&p);
    memset(inStack,false,sizeof(inStack));
    memset(newMoney,0,sizeof(newMoney));
    memset(isBar,false,sizeof(isBar));
    memset(dfn,0,sizeof(dfn));
    cnt = Time = 0;
    for(int i = 1; i <= n; i++) if(dfn[i] == 0) Tarjan(i);
    if(cnt == 1) {printf("%d",newMoney[cnt]);return 0;}
    for(int i=0;i<p;i++)
    {
      scanf("%d", &a);
      isBar[belong[a]] = true;
    }
    start = belong[s];
    for(int i =1; i <= n; i ++)
    {
        for(int j = 0; j < Gra[i].size(); j++){
            int k = Gra[i][j];
            if(belong[i] != belong[k]){
                newGra[belong[i]].push_back(belong[k]);
            }
        }
    }
 
    int ans = spfa();
    printf("%d", ans);
}

 

 看起来,STL和链式向前星相比,速度还是慢了不少的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<vector>
#include<queue>
#include<stack>
#include<set>
#include<algorithm>
using namespace std;
#define N 500001
stack<int>Sta;
queue<int>Que;
struct edge
{
    int u,v,next;
}edge1[N],edge2[N];
bool isBar[N],inStack[N];
int low[N],dfn[N],belong[N],money[N],newMoney[N],cnt,Time,start;
int maxMoney[N],head[N],head2[N];
 
void add(int u, int v, int id)
{
    edge1[id].u = u;
    edge1[id].v = v;
    edge1[id].next = head[u];
    head[u] = id;
}
 
void add2(int u, int v, int id)
{
    edge2[id].u = u;
    edge2[id].v = v;
    edge2[id].next = head2[u];
    head2[u] = id;
}
void Tarjan(int s)
{
    dfn[s] = low[s] = ++Time;
    Sta.push(s);
    inStack[s] = true;
    for(int u = head[s]; ~u; u = edge1[u].next)
    {
        int v = edge1[u].v;
        if(dfn[v] == 0){
            Tarjan(v);
            low[s] = min(low[s], low[v]);
        }
        else if(inStack[v] == true){
            low[s] = min(low[s], dfn[v]);
        }
    }
    if(dfn[s] == low[s])
        {
            cnt ++;
            while(!Sta.empty()){
              int temp = Sta.top(); Sta.pop();
              belong[temp] = cnt;
              newMoney[cnt] += money[temp];
              inStack[temp] = false;
              if(temp == s) break;
            }
        }
}
 
int spfa()
{
    int ans = 0;
    Que.push(start);
    memset(maxMoney,0,sizeof(maxMoney));
    maxMoney[start] = newMoney[start];
    while(!Que.empty())
    {
        int now = Que.front(); Que.pop();
        for(int u = head2[now]; ~u; u = edge2[u].next)
        {
            int v = edge2[u].v;
            if(maxMoney[now] + newMoney[v] > maxMoney[v])
            {
                maxMoney[v] = maxMoney[now] + newMoney[v];
                Que.push(v);
            }
            if(isBar[v]) ans = max(ans, maxMoney[v]);
        }
    }
    return ans;
}
 
int main()
{
    int n,m,a,b,s,p;
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    for (int i = 0; i < m; i++) {
      /* code */
      scanf("%d%d",&a, &b);
      add(a,b,i+1);
    }
    for (int i = 1; i <= n; i++) {
      /* code */
      scanf("%d",&money[i]);
    }
    scanf("%d%d",&s,&p);
    memset(inStack,false,sizeof(inStack));
    memset(newMoney,0,sizeof(newMoney));
    memset(isBar,false,sizeof(isBar));
    memset(dfn,0,sizeof(dfn));
    cnt = Time = 0;
    for(int i = 1; i <= n; i++) if(dfn[i] == 0) Tarjan(i);
    if(cnt == 1) {printf("%d",newMoney[cnt]);return 0;}
    for(int i=0;i<p;i++)
    {
      scanf("%d", &a);
      isBar[belong[a]] = true;
    }
    start = belong[s];
    memset(head2,-1,sizeof(head2));
    int kkk = 0;
    for(int i =1; i <= n; i ++)
    {
        for(int u = head[i]; ~u; u = edge1[u].next){
            int v = edge1[u].v;
            if(belong[i] != belong[v]){
                add2(belong[i],belong[v],++kkk);
            }
        }
    }
 
    int ans = spfa();
    printf("%d", ans);
}

Tarjan + bfs HYSBZ 1179Atm的更多相关文章

  1. 4612 warm up tarjan+bfs求树的直径(重边的强连通通分量)忘了写了,今天总结想起来了。

    问加一条边,最少可以剩下几个桥. 先双连通分量缩点,形成一颗树,然后求树的直径,就是减少的桥. 本题要处理重边的情况. 如果本来就两条重边,不能算是桥. 还会爆栈,只能C++交,手动加栈了 别人都是用 ...

  2. NOIP 2015提高组复赛

    神奇的幻方 题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行.每列及两条对角线上的数字之和都相同. 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第 ...

  3. hdu-4612(无向图缩点+树的直径)

    题意:给你n个点和m条边的无向图,问你如果多加一条边的话,那么这个图最少的桥是什么 解题思路:无向图缩点和树的直径,用并查集缩点: #include<iostream> #include& ...

  4. Codeforces Round #467(Div2)题解

    凌晨起来打CF,0:05,也是我第一次codeforces 第一题: 我刚开始怀疑自己读错题了,怎么会辣么水. 判除了0的数字种类 #include <cstdio> ; ]; int m ...

  5. 【题解】洛谷P3119 Grass Cownoisseur G

    题面:洛谷P3119 Grass Cownoisseur G 本人最近在熟悉Tarjan的题,刷了几道蓝题后,我飘了 趾高气扬地点开这道紫题,我一瞅: 哎呦!这不是分层图吗? 突然就更飘了~~~ 用时 ...

  6. 【BZOJ-2725】故乡的梦 Dijsktra + Tarjan + Dinic + BFS + 堆

    2725: [Violet 6]故乡的梦 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 502  Solved: 173[Submit][Status ...

  7. HDU4612+Tarjan缩点+BFS求树的直径

    tarjan+缩点+树的直径题意:给出n个点和m条边的图,存在重边,问加一条边以后,剩下的桥的数量最少为多少.先tarjan缩点,再在这棵树上求直径.加的边即是连接这条直径的两端. /* tarjan ...

  8. BZOJ 1194: [HNOI2006]潘多拉的盒子( BFS + tarjan + dp )

    O(S²)枚举2个诅咒机, 然后O(n²)BFS去判断. 构成一个有向图, tarjan缩点, 然后就是求DAG的最长路.. ------------------------------------- ...

  9. 【BFS】【并查集】【Tarjan】【LCA】Gym - 101173H - Hangar Hurdles

    给你一张地图,给你q次询问,每次问你从A点到B点,最大能移动多大的箱子. 把每个点所能容纳的最大箱子求出来(BFS,八连通,一开始将所有边界点和障碍点入队).然后从大到小排序.然后用并查集将相邻(四联 ...

随机推荐

  1. C# 添加Word页眉、页脚和页码

    在Word文档中,我们可以通过添加页眉.页脚的方式来丰富文档内容.添加页眉.页脚时,可以添加时间.日期.文档标题,文档引用信息.页码.内容解释.图片/LOGO等多种图文信息.同时也可根据需要调整文字或 ...

  2. jQuery(七)、效果和动画

    1 显示和隐藏 1.show([speed,[easing],[fn]]) 显示隐藏的匹配元素. 参数: (1) spend:三种预定速度之一的字符串('show','normal','fast')或 ...

  3. 2014年第五届蓝桥杯javaB组 试题 答案 解析

    1.武功秘籍 小明到X山洞探险,捡到一本有破损的武功秘籍(2000多页!当然是伪造的).他注意到:书的第10页和第11页在同一张纸上,但第11页和第12页不在同一张纸上. 小明只想练习该书的第81页到 ...

  4. Odoo 菜单美化的扩展模块

    详见: http://www.oejia.net/blog/2018/07/07/oejia_menu_about.html Odoo 菜单美化主题,odoo默认的菜单算是简洁好用的,如果您觉得还少了 ...

  5. Centos7 使用 kubeadm 安装Kubernetes 1.13.3

    目录 目录 什么是Kubeadm? 什么是容器存储接口(CSI)? 什么是CoreDNS? 1.环境准备 1.1.网络配置 1.2.更改 hostname 1.3.配置 SSH 免密码登录登录 1.4 ...

  6. ngnix简单使用

    NGINX是一个高性能HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器,是由伊戈尔·塞索耶夫为俄罗斯访问量第二的Rambler.ru站点开发的,第一个公版发布于2004年10月4日 ...

  7. Docker-镜像源加速配置

    Docker官网镜像服务在境外,拉取速度很比较慢,所以我们安装完Docker后一般会切换镜像源,将镜像源切换到国内以此达到加速的目的. 国内比较常用的Docker Hub镜像服务:1.阿里云2.Dao ...

  8. Neo4j 全文检索

    全文检索基本概念 搜索 搜索这个行为是用户与搜索引擎的一次交互过程,用户需要找一些数据,他提供给搜索引擎一些约束条件.搜索引擎通过约束条件抽取一些结果给用户 搜索引擎 搜索引擎存在的目的是存储,查找和 ...

  9. js坚持不懈之18:trim()方法

    trim()方法,类似Python中的strip(),用去去除字符串对象前后的空格. <!DOCTYPE html> <html> <body> <scrip ...

  10. 下载华为交换机MIB参考文件并使用snmpwalk获取OID信息

    1.下载交换机MIB参考文件访问 https://support.huawei.com/enterprise/zh/index.html,搜索交换机型号 点击案例库,选择MIB参考 下载文件 打开文件 ...