zoukankan      html  css  js  c++  java
  • 【最短路】2018-2019 ACM-ICPC Brazil Subregional Programming Contest L. Subway Lines

    下午小细节没处理好,然后WA了。晚上静心改了改就好了。开心!

    不过.....499ms?

    L. Subway Lines

    在网上搬了找重心的dfs代码。

    得找lca,但是我已经忘了该用什么算法,因为很久之前看的找lca的题/算法,但是太久没用,忘了.... 所以...就没用什么算法模板了。

    从重心G开始遍历,然后就,记录父亲。

    会超时。其实有这个想法,但是一开始打算碰碰运气..结果真的超时。

    所以要优化。 当节点的度数为2且父亲的度数为2时,可以将当前节点合并到父亲节点,这样子不断合并,就可以避免链式的n^2超时。

    既然要合并,就用一个数组记录一个点的真正价值,初始化都为1,合并的点的价值就加起来。

    然后就不会超时了。然后我就WA了。因为我忘记在合并的时候更改深度。

    晚上想起来了,就过了。

    嘻嘻。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #define debug printf("!");
    using namespace std;
    typedef __int64 ll;//%I64d
    const int mod=1e9+7;
    const int maxn=1e5+50;
    const int inf=0x3f3f3f3f;
    
    
    vector<int>p[maxn];
    int fath[maxn]={0},dep[maxn]={0};
    int son[maxn]={0},G,bal,n,val[maxn];
    
    void dfs(int v,int fa)
    {
        son[v]=0;
        int pbal=0,i,j,k;
        for(i=0;i<p[v].size();i++)
        {
            k=p[v][i];
            if(k!=fa)
            {
                dfs(k,v);
                son[v]+=son[k]+1;
                pbal=max(pbal,son[k]+1);
            }
        }
        pbal=max(pbal,n-son[v]-1);
        if(pbal<bal||(pbal==bal&&v<G))
        {
            G=v;
            bal=pbal;
        }
    }
    void gettree()
    {
        int now,k,kk;
        int vis[maxn]={0};
        queue<int> que;
        que.push(G);fath[G]=G;vis[G]=1,dep[G]=0;
        while(!que.empty())
        {
            now=que.front();que.pop();k=p[now].size();kk=p[fath[now]].size();
            for(int i=0;i<k;i++)
            {
                if(vis[p[now][i]])continue;
                vis[p[now][i]]=1;
                fath[p[now][i]]=now;
                if(k==2&&kk==2&&now!=G)fath[p[now][i]]=fath[now];
                dep[p[now][i]]=dep[fath[p[now][i]]]+1;
                que.push(p[now][i]);
            }
            if(k==2&&kk==2&&now!=G)val[fath[now]]+=val[now];
        }
    }
    int solve(int a,int b,int &fa,int viss[])
    {
        int ans=0;
        if(viss[a])ans+=val[a];
        else viss[a]=1;
        if(a!=b)
        {
            if(viss[b])ans+=val[b];
            else viss[b]=1; 
        }
        while(dep[a]>dep[b])
        {
            a=fath[a];
            if(viss[a])ans+=val[a];
            else viss[a]=1;
        }
        while(dep[b]>dep[a])
        {
            b=fath[b];
            if(viss[b])ans+=val[b];
            else viss[b]=1;
        }
        while(a!=b)
        {
            a=fath[a];
            if(viss[a])ans+=val[a];
            else viss[a]=1;
            if(a==b)break;
            b=fath[b];
            if(a==b)break;
            if(viss[b])ans+=val[b];
            else viss[b]=1;
        }
        fa=a;
        return ans;
    }
    int main()
    {
        int q,i,j,k,s,e,a,b,ans,c,d,fa1,fa2;
        scanf("%d%d",&n,&q);
        for(i=1;i<n;i++)
        {
            val[i]=1;
            scanf("%d%d",&s,&e);
            p[s].push_back(e);
            p[e].push_back(s);
        }val[n]=1;
        G=0;bal=inf;
        dfs(1,-1);
    //    printf("##G:%d
    ",G);
        gettree();
        while(q--)
        {
            int viss[maxn]={0};
            scanf("%d%d%d%d",&a,&b,&c,&d);
            solve(a,b,fa1,viss);
            ans=solve(c,d,fa2,viss);
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    腾讯云COS对象存储的简单使用
    SpringSecurity的简单使用
    AngularJS入门 & 分页 & CRUD示例
    使用 Java 发送邮件
    Java操作pdf: JarsperReport的简单使用
    获取Spring容器中的Bean协助调试
    JMS--ActiveMQ的简单使用
    Echarts和Quartz简介
    WebService
    Java使用 POI 操作Excel
  • 原文地址:https://www.cnblogs.com/kkkek/p/11514835.html
Copyright © 2011-2022 走看看