uestc 方老师抢银行

参考的大牛的思路和代码

思路: 每次经过一个强连通分量时,都可以走完该分量从而使抢得的钱最多,可以把每个强连通分量缩点,用总的钱数代表该点的值。然后重新遍历新图,遇到网吧可以更新一下结果。

 

  1 #include<iostream>

  2 #include<cstdio>

  3 #include<cstdlib>

  4 #include<cstring>

  5 #include<string>

  6 #include<queue>

  7 #include<algorithm>

  8 #include<map>

  9 #include<iomanip>

 10 #include<climits>

 11 #include<string.h>

 12 #include<cmath>

 13 #include<stdlib.h>

 14 #include<vector>

 15 #include<stack>

 16 #include<set>

 17 using namespace std;

 18 #define INF 1000000007

 19 #define MAXN 300010

 20 #define Mod 1000007

 21 #define N 100007

 22 #define NN 30

 23 #define sigma_size 3

 24 const int maxn = 6e5 + 10;

 25 using namespace std;

 26 typedef long long LL;

 27 const double pi = acos(-1);

 28 

 29 vector<int> G[MAXN], G2[MAXN];

 30 int dfn[N], lowlink[N], instk[N], bel[N], coin[N], iswb[N], wb[N], coin2[N];

 31 int n, m, dfs_clock, scc_cnt, p, k, res;

 32 int u, v;

 33 stack<int> S;

 34 

 35 void Tarjan(int u)

 36 {

 37     dfn[u] = lowlink[u] = ++dfs_clock;

 38     S.push(u);

 39     instk[u] = 1;

 40     for (int i = 0; i < G[u].size(); ++i) {

 41         int v = G[u][i];

 42         if (!dfn[v]) {

 43             Tarjan(v);

 44             lowlink[u] = min(lowlink[u], lowlink[v]);

 45         }

 46         else if (instk[v]) {

 47             lowlink[u] = min(lowlink[u], dfn[v]);

 48         }

 49     }

 50     if (lowlink[u] == dfn[u]) {            //找到一个强连通分量

 51         scc_cnt++;                        //强连通分量数目加一

 52         int v;

 53         do {

 54             v = S.top();

 55             S.pop();

 56             if (iswb[v]) wb[scc_cnt] = 1;

 57             instk[v] = 0;

 58             coin2[scc_cnt] += coin[v];

 59             bel[v] = scc_cnt;

 60             if (v == p) p = scc_cnt;

 61         } while (v != u);

 62     }

 63 }

 64 

 65 void find_scc()                            //Tarjan求强连通分量

 66 {

 67     for (int i = 1; i <= n; ++i)

 68         if (!dfn[i]) Tarjan(i);

 69 }

 70 

 71 void dfs(int u, int sum)                //遍历新建的图

 72 {

 73     sum += coin2[u];

 74     if (wb[u]) res = sum;

 75     for (int i = 0; i < G2[u].size(); ++i)

 76         dfs(G2[u][i], sum);

 77 }

 78 

 79 void init()

 80 {

 81     for (int i = 0; i <= n; ++i) {

 82         G[i].clear();

 83         G2[i].clear();

 84     }

 85     while (!S.empty()) S.pop();

 86     dfs_clock = scc_cnt = 0;

 87     memset(instk, 0, sizeof(instk));

 88     memset(dfn, 0, sizeof(dfn));

 89     memset(iswb, 0, sizeof(iswb));

 90     memset(wb, 0, sizeof(wb));

 91     memset(bel, -1, sizeof(bel));

 92     memset(coin2, 0, sizeof(coin2));

 93     memset(lowlink, 0, sizeof(lowlink));

 94 }

 95 

 96 void read()

 97 {

 98     for (int i = 0; i < m; ++i) {

 99         scanf("%d%d", &u, &v);

100         G[u].push_back(v);

101     }

102     for (int i = 1; i <= n; ++i)

103         scanf("%d", &coin[i]);

104     scanf("%d%d", &p, &k);

105     for (int i = 0; i < k; ++i) {

106         scanf("%d", &v);

107         iswb[v] = 1;

108     }

109 }

110 

111 void rebuild()                                //根据强连通分量重新建图

112 {

113     for (int i = 1; i <= n; ++i) {

114         for (int j = 0; j < G[i].size(); ++j) {

115             u = bel[i];

116             v = bel[G[i][j]];

117             if (u != v)

118                 G2[u].push_back(v);

119         }

120     }

121     res = -1;

122     dfs(p, 0);

123     cout << res << endl;

124 }

125 

126 void process()

127 {

128     init();

129     read();

130     find_scc();

131     rebuild();

132 }

133 

134 int main()

135 {

136     while (cin >> n >> m)

137         process();

138     //system("pause");

139     return 0;

140 }

 

你可能感兴趣的:(UE)