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\n",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\n",ans);
    }
}

猜你喜欢

转载自www.cnblogs.com/kkkek/p/11514835.html