zoukankan      html  css  js  c++  java
  • [IOI 2008] Island

    [题目链接]

             https://www.lydsy.com/JudgeOnline/problem.php?id=1791

    [算法]

            不难看出,要求的是这个基环树森林中每棵基环树的直径之和

    [代码]

              

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e6 + 10;
    
    struct edge
    {
            int to,w,nxt;
    } e[MAXN << 1];
    
    int i,v,w,tot,n,u,cnt;
    int degree[MAXN],belong[MAXN],head[MAXN];
    long long d[MAXN],f[MAXN],a[MAXN << 1],sum[MAXN << 1];
    long long ans;
    bool cal[MAXN];
    
    inline void addedge(int u,int v,int w)
    {
            tot++;
            e[tot] = (edge){v,w,head[u]};
            head[u] = tot;
    }
    inline void bfs(int u,int t)
    {
            int i,cur,v,w;
            queue< int > q;
            belong[u] = t;
            q.push(u);
            while (!q.empty())
            {
                    cur = q.front();
                    q.pop();
                    for (i = head[cur]; i; i = e[i].nxt)
                    {
                            v = e[i].to;
                            w = e[i].w;
                            if (!belong[v])
                            {
                                    belong[v] = t;
                                    q.push(v);
                            } 
                    }
            }
    }
    inline void topsort()
    {
            int i,u,v,w;
            queue< int > q;
            for (i = 1; i <= n; i++)
            {
                    if (degree[i] == 1)
                            q.push(i);        
            } 
            while (!q.empty())
            {
                    u = q.front();
                    q.pop();
                    for (i = head[u]; i; i = e[i].nxt)
                    {
                            v = e[i].to;
                            w = e[i].w;
                            if (degree[v] > 1)
                            {
                                    d[belong[u]] = max(d[belong[u]],f[u] + f[v] + w);
                                    f[v] = max(f[v],f[u] + w);
                                    if ((--degree[v]) == 1) q.push(v);
                            }
                    }
            }
    } 
    inline void dp(int t,int x)
    {
            long long i,l,r,y = x,m = 0,v,w;
            static int q[MAXN << 1];
            do
            {
                    a[++m] = f[y];
                    degree[y] = 1;
                    for (i = head[y]; i; i = e[i].nxt)
                    {
                            v = e[i].to;
                            w = e[i].w;
                            if (degree[v] > 1)
                            {
                                    y = v;
                                    sum[m + 1] = sum[m] + w;
                                    break;
                            }
                    }
            } while(i);
            if (m == 2)
            {
                    l = 0;
                    for (i = head[y]; i; i = e[i].nxt)
                    {
                            v = e[i].to;
                            w = e[i].w;
                            if (v == x) l = max(l,w);
                    }
                    d[t] = max(d[t],f[x] + f[y] + l);
                    return;
            }
            for (i = head[y]; i; i = e[i].nxt)
            {
                    v = e[i].to;
                    w = e[i].w;
                    if (v == x) 
                    {
                            sum[m + 1] = sum[m] + w;        
                            break;
                    }
            } 
            for (i = 1; i < m; i++) 
            {
                    a[m + i] = a[i];
                    sum[m + i] = sum[m + 1] + sum[i];
            }
            q[l = r = 1] = 1;
            for (i = 2; i <= 2 * m - 1; i++)
            {
                    while (l <= r && i - q[l] >= m) l++;
                    d[t] = max(d[t],a[q[l]] + a[i] + sum[i] - sum[q[l]]);
                    while (l <= r && a[q[r]] - sum[q[r]] <= a[i] - sum[i]) r--;
                    q[++r] = i;
            }
    }
    int main() 
    {
            
            scanf("%d",&n);
            for (u = 1; u <= n; u++)
            {
                    scanf("%d%d",&v,&w);
                    addedge(u,v,w);
                    addedge(v,u,w);
                    degree[u]++; degree[v]++;
            }
            for (i = 1; i <= n; i++)
            {
                    if (!belong[i])    
                            bfs(i,++cnt);
            }    
            topsort();
            for (i = 1; i <= n; i++)
            {
                    if (degree[i] > 1 && !cal[belong[i]])
                    {
                            cal[belong[i]] = true;
                            dp(belong[i],i);
                          ans += d[belong[i]]; 
                    }
            }
            printf("%lld
    ",ans);
            
            return 0;
        
    }

              

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 黑色星期五
    Java实现 蓝桥杯VIP 算法训练 比赛安排
    Java实现 蓝桥杯VIP 算法训练 比赛安排
    Java实现 蓝桥杯VIP 算法训练 斜率计算
    Java实现 蓝桥杯VIP 算法训练 斜率计算
    Java实现 蓝桥杯VIP 算法训练 整数平均值
    Java实现 蓝桥杯VIP 算法训练 整数平均值
    控件动态产生器(使用RegisterClasses提前进行注册)
    Delphi编写自定义控件以及接口的使用(做了一个TpgDbEdit)
    Log4delphi使用心得
  • 原文地址:https://www.cnblogs.com/evenbao/p/9391100.html
Copyright © 2011-2022 走看看