模板题求调

P3806 【模板】点分治 1

Night_sea_64 @ 2023-06-08 19:43:39

#include<iostream>
#include<vector>
#include<cstring>
using namespace std;
int n,m,k,d[10010],sz[10010],maxpart[10010];
struct edge{int x,w;bool f;};
vector<edge>v[10010],v2[10010];
int a[10010],cur;
bool flag[10000010],ans;
void dfs1(int x,int last)
{
    sz[x]=1;
    for(int i=0;i<v[x].size();i++)if(v[x][i].f)
        if(v[x][i].x!=last)
        {
            dfs1(v[x][i].x,x);
            sz[x]+=sz[v[x][i].x];
            maxpart[x]=max(maxpart[x],sz[v[x][i].x]);
        }
}
int find(int x)
{
    for(int i=1;i<=n;i++)
        maxpart[i]=sz[i]=0;
    dfs1(x,0);
    int minn=1e9,minid=0;
    for(int i=1;i<=n;i++)
    {
        maxpart[i]=max(maxpart[i],sz[x]-sz[i]);
        if(maxpart[i]<minn)
            minn=maxpart[i],minid=i;
    }
    return minid;
}
void dfs2(int x,int last)
{
    if(d[x]>k)return;
    if(flag[k-d[x]])ans=1;
    if(ans)return;
    for(int i=0;i<v[x].size();i++)
        if(v[x][i].x!=last)
        {
            d[v[x][i].x]=d[x]+v[x][i].w;
            dfs2(v[x][i].x,x);
        }
}
void dfs3(int x,int last)
{
    if(d[x]>k)return;
    if(!flag[d[x]])
    {
        flag[d[x]]=1;
        a[++cur]=d[x];
    }
    for(int i=0;i<v[x].size();i++)
        if(v[x][i].x!=last)
            dfs3(v[x][i].x,x);
}
void solve(int x)
{
    x=find(x);
    memset(d,0,sizeof(d));
    flag[0]=1;
    a[++cur]=0;
    for(int i=0;i<v[x].size();i++)if(v[x][i].f)
    {
        d[v[x][i].x]=v[x][i].w;
        dfs2(v[x][i].x,x);
        dfs3(v[x][i].x,x);
    }
    for(int i=1;i<=cur;i++)
        flag[a[i]]=0;
    cur=0;
    if(ans)return;
    v2[x]=v[x];
    for(int i=1;i<=n;i++)
        for(int j=0;j<v[i].size();j++)
            if(i==x||v[i][j].x==x)v[i][j].f=0;
    for(int i=0;i<v2[x].size();i++)if(v2[x][i].f)
        solve(v[x][i].x);
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<n;i++)
    {
        int x,y,w;
        cin>>x>>y>>w;
        v[x].push_back({y,w,1});
        v[y].push_back({x,w,1});
    }
    while(m--)
    {
        ans=0;
        for(int i=1;i<=n;i++)
            for(int j=0;j<v[i].size();j++)
                v[i][j].f=1;
        cin>>k;
        solve(1);
        cout<<(ans?"AYE":"NAY")<<endl;
    }
    return 0;
}

我的代码 T 了四个点(如果把找重心那里删掉只会 T 三个),请问我应该优化哪里呢?


by Night_sea_64 @ 2023-06-08 19:48:00

哦,看到了 https://www.luogu.com.cn/discuss/188596 我先改成只点分治一次


by cjwdyzxfblzs @ 2023-06-08 20:08:46

@Netherite_sword_666 不能每次跑一个,应该离线下来,查看询问,跑一次


by Night_sea_64 @ 2023-06-08 20:34:51

@sjzez__chess 感谢大佬,我就打算这么改了


|