nullzero

Islands [bug]

Sep 15th, 2012
128
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.14 KB | None | 0 0
  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <vector>
  4. #include <stack>
  5. #include <bitset>
  6.  
  7. using namespace std;
  8.  
  9. typedef long long ll;
  10. typedef pair<ll,ll> II;
  11.  
  12. const int N(1000001);
  13. const int WHITE(0);
  14. const int GREY(1);
  15. const int BLACK(2);
  16. const ll INF(1e9);
  17.  
  18. vector<pair<int,int> > V[N], cycle[N];
  19. ll lengthpath[N];
  20. int numcomponent;
  21. bitset<N> incycle;
  22. bitset<N> visited;
  23. char color[N];
  24. int parent[N];
  25. int component[N];
  26.  
  27. bool find_cycle(int node){
  28.     bool foundcycle = false;
  29.     int markcycle = -1, now = -1;
  30.     stack<int> S;
  31.     S.push(node);
  32.     while(not S.empty()){
  33.         int top = S.top();
  34.         S.pop();
  35.         if(visited[top]) continue;
  36.         visited[top] = true;
  37.         component[node] = numcomponent;
  38.         for(int i = 0; i < (int)V[top].size(); ++i) S.push(V[top][i].first);
  39.     }
  40.    
  41.     S.push(node);
  42.     while(not S.empty()){
  43.         int top = S.top();
  44.         S.pop();
  45.         if(color[top] == BLACK) continue;
  46.         if(color[top] == GREY){
  47.             color[top] = BLACK;
  48.             continue;
  49.         }
  50.         color[top] = GREY;
  51.         S.push(top);
  52.         for(int i = 0; i < (int)V[top].size(); ++i){
  53.             if(V[top][i].first == parent[top]) continue;
  54.             if(color[V[top][i].first] == GREY){
  55.                 foundcycle = true;
  56.                 markcycle = V[top][i].first;
  57.                 now = top;
  58.                 cycle[numcomponent].push_back(V[top][i]);
  59.                 break;
  60.             }
  61.             S.push(V[top][i].first);
  62.             parent[V[top][i].first] = top;
  63.             lengthpath[V[top][i].first] = V[top][i].second;
  64.         }
  65.         if(foundcycle) break;
  66.     }
  67.     if(not foundcycle) return false;
  68.     while(now != markcycle){
  69.         incycle[now] = true;
  70.         cycle[numcomponent].push_back(make_pair(now, lengthpath[now]));
  71.         now = parent[now];
  72.     }
  73.     incycle[markcycle] = true;
  74.     return true;
  75. }
  76.  
  77. bool firsttime;
  78. ll subopt;
  79. ll opt[N];
  80.  
  81. ll calcdyn(int node){
  82.     if(firsttime) firsttime = false;
  83.     else if(incycle[node]) return -INF;
  84.     if(visited[node]) return opt[node];
  85.     visited[node] = true;
  86.     ll vmax = 0, vmax2 = 0;
  87.     for(int i = 0; i < (int)V[node].size(); ++i){
  88.         if(parent[node] == V[node][i].first) continue;
  89.         parent[V[node][i].first] = node;
  90.         ll val = calcdyn(V[node][i].first) + (ll)V[node][i].second;
  91.         if(val > vmax){
  92.             vmax2 = vmax;
  93.             vmax = val;
  94.         }else if(val > vmax2){
  95.             vmax2 = val;
  96.         }
  97.         subopt = max(subopt, vmax + vmax2);
  98.     }
  99.     return opt[node] = vmax;
  100. }
  101.  
  102. ll dynamic_tree(int node){
  103.     firsttime = true;
  104.     subopt = 0;
  105.     return calcdyn(node);
  106. }
  107.  
  108. II sum[N], cul[N];
  109. int p[N];
  110.  
  111. ll solve(vector<ll>& node, vector<ll>& edge){
  112.     sum[0] = cul[0] = II(node[0], 0);
  113.     for(int i = 1; i < (int)node.size(); ++i)
  114.         sum[i] = cul[i] = II(cul[i - 1].first - node[i - 1] + edge[i - 1] + node[i], i);
  115.    
  116.     sort(sum, sum + node.size(), greater<II>());
  117.     ll ans1 = 0;
  118.     int pointer = 0;
  119.     for(int i = 0; i < (int)node.size() - 1; ++i){
  120.         if(sum[pointer].second <= i) pointer++;
  121.         ans1 = max(ans1, (node[i] << 1) + sum[pointer].first - cul[i].first);
  122.     }
  123.     ll ans2 = 0;
  124.     ll cultivate = node.back();
  125.     pointer = 0;
  126.     for(int i = (int)node.size() - 2; i >= 0; --i){
  127.         while(sum[pointer].second > i) pointer++;
  128.         ans2 = max(ans2, cultivate + sum[pointer].first);
  129.         cultivate += edge[i] + node[i] - node[i + 1];
  130.     }
  131.     return max(ans1, ans2 + edge.back());
  132. }
  133.  
  134. int main(){
  135.     int n, a, b;
  136.     ll ans = 0;
  137.     scanf("%d", &n);
  138.     for(int i = 1; i <= n; ++i){
  139.         scanf("%d %d", &a, &b);
  140.         if(i == a) continue;
  141.         if(a < i and p[a] == i){
  142.             for(int j = 0; j < (int)V[i].size(); ++j)
  143.                 if(V[i][j].first == a) V[i][j].second = max(V[i][j].second, b);
  144.             for(int j = 0; j < (int)V[a].size(); ++j)
  145.                 if(V[a][j].first == i) V[a][j].second = max(V[a][j].second, b);
  146.             continue;
  147.         }
  148.         p[i] = a;
  149.         V[i].push_back(make_pair(a, b));
  150.         V[a].push_back(make_pair(i, b));
  151.     }
  152.     for(int i = 1; i <= n; ++i){
  153.         if(V[i].size() == 0) continue;
  154.         if(visited[i]) continue;
  155.         if(not find_cycle(i)) cycle[numcomponent].push_back(II(i, -1));
  156.         numcomponent++;
  157.     }
  158.     for(int i = 0; i < N; ++i) color[i] = WHITE, visited[i] = false, parent[i] = 0;
  159.     for(int i = 0; i < numcomponent; ++i){
  160.         if(not incycle[cycle[i][0].first]){
  161.             ll tmp = dynamic_tree(cycle[i][0].first);
  162.             ans += max(tmp, subopt);
  163.             continue;
  164.         }
  165.         vector<ll> node, edge;
  166.         node.push_back(dynamic_tree(cycle[i][0].first));
  167.         ll anssub = subopt;
  168.         for(int j = 0; j < (int)cycle[i].size() - 1; ++j){
  169.             edge.push_back(cycle[i][j].second);
  170.             node.push_back(dynamic_tree(cycle[i][j + 1].first));
  171.             anssub = max(anssub, subopt);
  172.         }
  173.         edge.push_back(cycle[i].back().second);
  174.         ans += max(anssub, solve(node, edge));
  175.     }
  176.     printf("%lld\n", ans);
  177.     return 0;
  178. }
Advertisement
Add Comment
Please, Sign In to add comment