IOI2008 Island 岛屿

Posted liguanlin1124

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IOI2008 Island 岛屿相关的知识,希望对你有一定的参考价值。

题目描述:

bz

luogu

题解:

裸的基环树直径。

代码:

技术图片
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 1000050;
template<typename T>
inline void read(T&x)
{
    T f = 1,c = 0;char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){c=c*10+ch-0;ch=getchar();}
    x = f*c;
}
int n,hed[N],cnt=1;
ll ans;
struct EG
{
    int to,nxt;
    ll w;
}e[2*N];
void ae(int f,int t,ll w)
{
    e[++cnt].to = t;
    e[cnt].nxt = hed[f];
    e[cnt].w = w;
    hed[f] = cnt;
}
int sta[2*N],tl,rt;
ll ste[N];
bool vis[N],cir[N],use[N];
int dfs0(int u,int pre)
{
    if(vis[u])
    {
        rt = u;
        return 1;
    }
    vis[u] = 1;
    for(int j=hed[u],now;j;j=e[j].nxt)
    {
        int to = e[j].to;
        if(j==pre)continue;
        if((now=dfs0(to,j^1)))
        {
            if(now==1)
            {
                sta[++tl] = u;
                ste[tl] = e[j].w;
                cir[u] = 1;
                if(u!=rt)return 1;
            }
            return 2;
        }
    }
    return 0;
}
int fa[N];
ll dp[N],sum[2*N],st[2*N],h,l,now;
void bfs(int u)
{
    h = 1,l = 0;
    st[++l] = u;
    use[u]=1;
    while(h<=l)
    {
        u = st[h++];
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(use[to]||cir[to])continue;
            use[to] = 1;
            fa[to] = u;
            st[++l] = to;
        }
    }
    for(int i=l;i>=1;i--)
    {
        u = st[i];
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(cir[to]||to==fa[u])continue;
            ll tmp = dp[to]+e[j].w;
            now = max(now,dp[u]+tmp);
            dp[u]=max(dp[u],tmp);
        }
    }
}
int main()
{
//  freopen("tt.in","r",stdin);
    read(n);
    for(int f,w,i=1;i<=n;i++)
    {
        read(f),read(w);
        ae(f,i,w),ae(i,f,w);
    }
    for(int i=1;i<=n;i++)if(!use[i])
    {
        tl=0;now=0;
        dfs0(i,0);
        for(int j=1;j<=tl;j++)
            bfs(sta[j]),sta[j+tl]=sta[j];
        if(tl==1)
        {
            now = max(now,dp[sta[1]]+ste[1]);
            ans+=now;
            continue;
        }
        for(int j=1;j<=tl;j++)sum[j]=sum[j-1]+ste[j];
        for(int j=1;j<=tl;j++)sum[j+tl]=sum[j+tl-1]+ste[j];
        h = 1,l = 0;
        for(int j=1;j<=2*tl;j++)
        {
            while(h<l&&st[h]+tl<=j)h++;
            if(h<=l)now = max(now,dp[sta[j]]+sum[j]+dp[sta[st[h]]]-sum[st[h]]);
            while(h<l&&dp[sta[st[l]]]-sum[st[l]]<dp[sta[j]]-sum[j])l--;
            st[++l] = j;
        }
        ans+=now;
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

 

以上是关于IOI2008 Island 岛屿的主要内容,如果未能解决你的问题,请参考以下文章

[IoI2008]Island 岛屿

[bzoj1791][ioi2008]Island 岛屿(基环树树的直径)

bzoj 1791: [Ioi2008]Island 岛屿基环树+单调队列优化dp

岛屿(bzoj1791)

IOI2008 island

[IOI2008]Island