码迷,mamicode.com
首页 > Windows程序 > 详细

BZOJ 1179 [Apio2009]Atm

时间:2015-12-11 23:55:56      阅读:258      评论:0      收藏:0      [点我收藏+]

标签:

第一眼看到题目被吓傻。。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 }
BZOJ 1179

 

BZOJ 1179 [Apio2009]Atm

标签:

原文地址:http://www.cnblogs.com/Created-equal/p/5040459.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!