• [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;
        
    }

              

  • 相关阅读:
    paip.提升性能C#.NET程序内存占用过多以及OutOfMemory解决方法
    ATTILAX项目进展表VC425
    paip.VOB DVD视频的无损分割与截取
    paip.程序不报错自动退出的解决
    paip.TechExcel DevSuite IIS 应用配置
    paip.软件版本完善计划C426fromVC423
    paip.chrome使用ACTIVX 的总结
    PAIP批量改名JS实现
    Source Navigato rNG4.4在ubuntu的简单的安装
    QuartusII编译出错小小总结
  • 原文地址:https://www.cnblogs.com/evenbao/p/9391100.html
Copyright © 2020-2023  润新知