标签:
第一眼看到题目被吓傻。。maya有向图上单源最长路。。?
后来仔细理解题意发现。。抢了一个ATM中的现金后这个ATM中就没有现金了。。
然后我们可以想到,可以在某个强联通分量中不断绕圈抢劫!直到所有的现金全部被抢完。。
毫不犹豫打个Tarjan缩点上去,每个点的点权是该点对应的强连通分量中所有点的点权(ATM中的现金)之和
然后就成了一个DAG啦,之后就是DAG上的最长路,这个可以用DP求,也可以像我一样用SPFA来求
1 #include <stack> 2 #include <queue> 3 #include <cstdio> 4 5 using namespace std; 6 7 const size_t Max_N(500050); 8 const size_t Max_M(500050); 9 10 size_t N, M; 11 12 //原图 13 unsigned int Head[Max_N]; 14 unsigned int To[Max_M], Next[Max_M]; 15 unsigned int Money[Max_N]; 16 17 //缩点后的新图 18 unsigned int SCC_Total; 19 unsigned int Edge_Total; 20 unsigned int SCC_Head[Max_N]; 21 unsigned int SCC_To[Max_M], SCC_Next[Max_M]; 22 unsigned int SCC_Weight[Max_N]; 23 unsigned int SCC_Number[Max_N]; 24 25 inline 26 unsigned int Min(const unsigned int &a, const unsigned int &b) 27 { 28 return a < b ? a : b; 29 } 30 31 inline 32 unsigned int Max(const unsigned int &a, const unsigned int &b) 33 { 34 return a > b ? a : b; 35 } 36 37 inline 38 void Add_Edge(const size_t &Total, const size_t &s, const size_t &t) 39 { 40 To[Total] = t, Next[Total] = Head[s], Head[s] = Total; 41 } 42 43 inline 44 void SCC_Add_Edge(const size_t &s, const size_t &t) 45 { 46 ++Edge_Total, SCC_To[Edge_Total] = t, SCC_Next[Edge_Total] = SCC_Head[s], SCC_Head[s] = Edge_Total; 47 } 48 49 void init() 50 { 51 size_t A, B; 52 53 scanf("%u%u", &N, &M); 54 for (size_t i = 1;i <= M;++i) 55 { 56 scanf("%u%u", &A, &B); 57 Add_Edge(i, A, B); 58 } 59 for (size_t i = 1;i <= N;++i) 60 scanf("%u", Money + i); 61 } 62 63 unsigned int Dfs_Clock; 64 unsigned int Pre[Max_N], Low_Link[Max_N]; 65 stack<unsigned int> Sta; 66 void Tarjan(const size_t &u) 67 { 68 Pre[u] = Low_Link[u] = ++Dfs_Clock; 69 Sta.push(u); 70 71 size_t v; 72 for (size_t i = Head[u];i;i = Next[i]) 73 { 74 v = To[i]; 75 if (!Pre[v]) 76 { 77 Tarjan(v); 78 Low_Link[u] = Min(Low_Link[u], Low_Link[v]); 79 } 80 else 81 if (!SCC_Number[v]) 82 Low_Link[u] = Min(Low_Link[u], Pre[v]); 83 } 84 85 if (Pre[u] == Low_Link[u]) 86 { 87 ++SCC_Total; 88 while (true) 89 { 90 v = Sta.top(); 91 Sta.pop(); 92 SCC_Number[v] = SCC_Total; 93 SCC_Weight[SCC_Total] += Money[v]; 94 if (u == v) 95 break; 96 } 97 } 98 } 99 100 void Make_Graph() 101 { 102 size_t t; 103 for (size_t s = 1;s <= N;++s) 104 for (size_t i = Head[s];i;i = Next[i]) 105 { 106 t = To[i]; 107 if (SCC_Number[s] != SCC_Number[t]) 108 SCC_Add_Edge(SCC_Number[s], SCC_Number[t]); 109 } 110 } 111 112 bool In_Q[Max_N]; 113 unsigned int Dist[Max_N]; 114 queue<unsigned int> Q; 115 void SPFA() 116 { 117 size_t S; 118 scanf("%u", &S); 119 120 Q.push(SCC_Number[S]); 121 In_Q[SCC_Number[S]] = true; 122 Dist[SCC_Number[S]] = SCC_Weight[SCC_Number[S]]; 123 124 unsigned int Top; 125 while (Q.size()) 126 { 127 Top = Q.front(); 128 Q.pop(); 129 In_Q[Top] = false; 130 131 for (size_t i = SCC_Head[Top];i;i = SCC_Next[i]) 132 if (Dist[SCC_To[i]] < Dist[Top] + SCC_Weight[SCC_To[i]]) 133 { 134 Dist[SCC_To[i]] = Dist[Top] + SCC_Weight[SCC_To[i]]; 135 if (!In_Q[SCC_To[i]]) 136 { 137 In_Q[SCC_To[i]] = true; 138 Q.push(SCC_To[i]); 139 } 140 } 141 } 142 143 unsigned int P; 144 unsigned int Ans(0); 145 scanf("%u", &P); 146 while (P--) 147 { 148 scanf("%u", &S); 149 Ans = Max(Ans, Dist[SCC_Number[S]]); 150 } 151 152 printf("%u", Ans); 153 } 154 155 int main() 156 { 157 init(); 158 159 for (size_t i = 1;i <= N;++i) 160 if (!Pre[i]) 161 Tarjan(i); 162 Make_Graph(); 163 164 SPFA(); 165 166 return 0; 167 }
标签:
原文地址:http://www.cnblogs.com/Created-equal/p/5040459.html