uestc 方老师抢银行
2015-03-08 22:35
253 查看
参考的大牛的思路和代码
思路: 每次经过一个强连通分量时,都可以走完该分量从而使抢得的钱最多,可以把每个强连通分量缩点,用总的钱数代表该点的值。然后重新遍历新图,遇到网吧可以更新一下结果。
思路: 每次经过一个强连通分量时,都可以走完该分量从而使抢得的钱最多,可以把每个强连通分量缩点,用总的钱数代表该点的值。然后重新遍历新图,遇到网吧可以更新一下结果。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<map> #include<iomanip> #include<climits> #include<string.h> #include<cmath> #include<stdlib.h> #include<vector> #include<stack> #include<set> using namespace std; #define INF 1000000007 #define MAXN 300010 #define Mod 1000007 #define N 100007 #define NN 30 #define sigma_size 3 const int maxn = 6e5 + 10; using namespace std; typedef long long LL; const double pi = acos(-1); vector<int> G[MAXN], G2[MAXN]; int dfn , lowlink , instk , bel , coin , iswb , wb , coin2 ; int n, m, dfs_clock, scc_cnt, p, k, res; int u, v; stack<int> S; void Tarjan(int u) { dfn[u] = lowlink[u] = ++dfs_clock; S.push(u); instk[u] = 1; for (int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if (!dfn[v]) { Tarjan(v); lowlink[u] = min(lowlink[u], lowlink[v]); } else if (instk[v]) { lowlink[u] = min(lowlink[u], dfn[v]); } } if (lowlink[u] == dfn[u]) { //找到一个强连通分量 scc_cnt++; //强连通分量数目加一 int v; do { v = S.top(); S.pop(); if (iswb[v]) wb[scc_cnt] = 1; instk[v] = 0; coin2[scc_cnt] += coin[v]; bel[v] = scc_cnt; if (v == p) p = scc_cnt; } while (v != u); } } void find_scc() //Tarjan求强连通分量 { for (int i = 1; i <= n; ++i) if (!dfn[i]) Tarjan(i); } void dfs(int u, int sum) //遍历新建的图 { sum += coin2[u]; if (wb[u]) res = sum; for (int i = 0; i < G2[u].size(); ++i) dfs(G2[u][i], sum); } void init() { for (int i = 0; i <= n; ++i) { G[i].clear(); G2[i].clear(); } while (!S.empty()) S.pop(); dfs_clock = scc_cnt = 0; memset(instk, 0, sizeof(instk)); memset(dfn, 0, sizeof(dfn)); memset(iswb, 0, sizeof(iswb)); memset(wb, 0, sizeof(wb)); memset(bel, -1, sizeof(bel)); memset(coin2, 0, sizeof(coin2)); memset(lowlink, 0, sizeof(lowlink)); } void read() { for (int i = 0; i < m; ++i) { scanf("%d%d", &u, &v); G[u].push_back(v); } for (int i = 1; i <= n; ++i) scanf("%d", &coin[i]); scanf("%d%d", &p, &k); for (int i = 0; i < k; ++i) { scanf("%d", &v); iswb[v] = 1; } } void rebuild() //根据强连通分量重新建图 { for (int i = 1; i <= n; ++i) { for (int j = 0; j < G[i].size(); ++j) { u = bel[i]; v = bel[G[i][j]]; if (u != v) G2[u].push_back(v); } } res = -1; dfs(p, 0); cout << res << endl; } void process() { init(); read(); find_scc(); rebuild(); } int main() { while (cin >> n >> m) process(); //system("pause"); return 0; }
相关文章推荐
- UESTC 901 方老师抢银行 --Tarjan求强连通分量
- UESTC 914 -- 方老师分身 I(Dijkstra)
- 2014 UESTC Training for Search Algorithm Problem F 方老师与迷宫
- 2014 UESTC Training for Graph Theory Problem G 方老师分身 I
- UESTC 方老师与迷宫
- uestc 方老师和农场
- 2014 UESTC Training for Graph Theory Problem H 方老师的分身 II
- uestc 方老师分身 I
- uestc 方老师炸弹
- UESTC_方老师和农场 2015 UESTC Training for Graph Theory<Problem L>
- uestc 方老师的分身 III 拓扑排序
- UESTC 898 方老师和缘分 --二分图匹配+强连通分量
- 2014 UESTC Training for Graph Theory Problem I 方老师的分身 III
- UESTC 899 方老师和农场 --双连通分量的构造
- 2016 UESTC Training for Dynamic Programming M - 柱爷抢银行欢庆5.1special 递推
- UESTC 900 方老师炸弹 --Tarjan求割点及删点后连通分量数
- uestc 方老师的分身 II
- UESTC_方老师分身 I CDOJ 914
- UESTC 883 方老师与两个串 --二分搜索+DP
- UESTC 方老师开橙卡