Tarjan + bfs HYSBZ 1179Atm

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的单向的道路到达其中的至少一个酒吧。

来源: http://www.lydsy.com/JudgeOnline/problem.php?id=1179


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);

}

来源: http://tool.oschina.net/highlight

看起来,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);

}

时间: 2024-10-29 22:27:02

Tarjan + bfs HYSBZ 1179Atm的相关文章

Tarjan总结

在图论中,连通图基于连通的概念.在一个无向图G中,若从顶点到顶点有路径相连(当然从到也一定有路径),则称和是连通的.如果G是有向图,那么连接和的路径中所有的边都必须同向.如果图中任意两点都是连通的,那么图被称作连通图.图的连通性是图的基本性质. 将有向图的所有的有向边替换为无向边,所得到的图称为原图的基图.如果一个有向图的基图是连通图,则有向图是弱连通图,弱有向图的任意两点都可以相互到达那么称这个有向图为强连通图,如果一个有向图的子图是强连通图,那么这个子图称为该有向图的强连通分量.有向图中一个

Codeforces Round #467(Div2)题解

凌晨起来打CF,0:05,也是我第一次codeforces 第一题: 我刚开始怀疑自己读错题了,怎么会辣么水. 判除了0的数字种类 #include <cstdio> int n,ans=0; bool hsh[610]; int main(){ scanf("%d",&n);int i; for(i=1;i<=n;++i){ int x;scanf("%d",&x);if(!hsh[x] && x)++ans,hs

BZOJ 1194 HNOI2006 潘多拉的盒子 BFS+Tarjan+拓扑序DP

题目大意:给定一些自动机,如果某个自动机A能产生的所有串都能在自动机B中产生,则称B是A的一个升级,求最长链 这题TM有毒 数据范围50,暴力枚举每一对点之间的关系,然后Tarjan缩点求最长链就行了 现在对于一对自动机A和B,我想知道A能产生的所有串是否都能在B中产生,那么BFS就可以了 我们用一个二元组(x,y)表示走了某个串后A走到了节点x,B走到了节点y,那么如果x是输出节点而y不是,则不满足条件,否则继续广搜(x,y)的两个后继 由于这样的二元组(x,y)只有O(n2)个,因此标记一下

有向图的强连通分量(tarjan算法)

强连通分量 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.有向图的极大强连通子图,称为强连通分量(strongly connected components). 考虑强连通分量C,设其中第一个被发现的点为x,则,C中其他的点都是x的后代.我们希望在x访问完成时立即输出C(可以同时记录C,输出代表

【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点

1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1685  Solved: 724[Submit][Status][Discuss] Description A,B两个国家正在交战,其中A国的物资运输网中有N个中转站,M条单向道路.设其中第i (1≤i≤M)条道路连接了vi,ui两个中转站,那么中转站vi可以通过该道路到达ui中转站,如果切断这条道路,需要代价ci.现在B国想找出一个路径切断方案

tarjan缩点以及链式前向星的基本+应用(洛谷1262 间谍网络)

题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B.有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手中掌握的全部情报.所以,如果我们能够收买一些间谍的话,我们就可能控制间谍网中的每一分子.因为一旦我们逮捕了一个间谍,他手中掌握的情报都将归我们所有,这样就有可能逮捕新的间谍,掌握新的情报. 我们的反间谍机关提供了一份资料,色括所有已知的受贿的间谍,以及他们愿意收受的具体数额.同时我们还知道哪些间谍手中具体掌握了哪些

【BZOJ-1179】Atm Tarjan + SPFA

1179: [Apio2009]Atm Time Limit: 15 Sec  Memory Limit: 162 MBSubmit: 2407  Solved: 993[Submit][Status][Discuss] Description Input 第一行包含两个整数N.M.N表示路口的个数,M表示道路条数.接下来M行,每行两个整数,这两个整数都在1到N之间,第i+1行的两个整数表示第i条道路的起点和终点的路口编号.接下来N行,每行一个整数,按顺序表示每个路口处的ATM机中的钱数.接下来

UVA 11324.The Largest Clique tarjan缩点+拓扑dp

题目链接:https://vjudge.net/problem/UVA-11324 题意:求一个有向图中结点数最大的结点集,使得该结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相互可达也可以). 思路:同一个强联通分量中满足结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相互可达也可以).把强联通分量收缩点后得到scc图,让每个scc结点的权值等于他的结点数,则求scc图上权最大的路径.拓扑dp,也可以直接bfs,但是要建立一个新的起点,连接所有入度为0

codeforces GYM 100114 J. Computer Network tarjan 树的直径 缩点

J. Computer Network Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Description The computer network of “Plunder & Flee Inc.” consists of n servers and m two-way communication links. Two servers can communicate either thr