参考的大牛的思路和代码
思路: 每次经过一个强连通分量时,都可以走完该分量从而使抢得的钱最多,可以把每个强连通分量缩点,用总的钱数代表该点的值。然后重新遍历新图,遇到网吧可以更新一下结果。
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 }