Internet_Explore 2024-05-30 12:41 采纳率: 20%
浏览 0

P1967 [NOIP2013 提高组] 货车运输 kruscal+树上倍增 求调

P1967 [NOIP2013 提高组] 货车运输

img

求调!

欢迎非AI回答!

不欢迎借鉴GPT的回答!

Code:

#include<cstdio>
#include<algorithm>
#include<utility>
#include<vector>
using namespace std;

#define N 1005
#define int long long
#define inf 9e18
#define min(a,b) (a<b?a:b)

int n,m;
vector<pair<int,int> >map[N],tree[N];
int root[N],depth[N];
pair<int,int>fa[N][15];

inline int find(int v)
{
    if(root[v]==v)
        return v;
    return root[v]=find(root[v]);
}

inline void Union(int x,int y){root[find(x)]=find(y);}

vector<pair<int,pair<int,int> > >edge;
void kruskal()
{
    for(int i=1;i<=n;++i)
        root[i]=i;
    for(int i=1;i<=n;++i)
        for(auto j:map[i])
            edge.push_back({j.second,{i,j.first}});
    sort(edge.begin(),edge.end(),greater<pair<int,pair<int,int> > >());
    for(int i=1;i<=m;++i)
    {
        auto Edge=edge[i];
        if(find(Edge.second.first)!=find(Edge.second.second))
        {
            Union(Edge.second.first,Edge.second.second);
            tree[Edge.second.first].push_back({Edge.second.second,Edge.first});
            tree[Edge.second.second].push_back({Edge.second.first,Edge.first});
        }
    }
}

void init(int i,int father,int w)
{
    fa[i][0].first=father;
    fa[i][0].second=w;
    depth[i]=depth[father]+1;
    for(int j=1;j<15;++j)
        fa[i][j].first=fa[fa[i][j-1].first][j-1].first,
        fa[i][j].second=min(fa[i][j-1].second,fa[fa[i][j-1].first][j-1].second);
    for(auto j:tree[i])
        if(j.first!=father)
            init(j.first,i,j.second);
}

int len(int x,int y)
{
    if(!(find(x)&&find(y))||find(x)!=find(y))
        return -1;
    if(depth[x]<depth[y])
        swap(x,y);
    int ans=inf;
    for(int i=0,j=depth[x]-depth[y];(1<<i)<=j;++i)
        if((1<<i)&j)
            ans=min(ans,fa[x][i].second),
            x=fa[x][i].first;
    if(x==y)
        return ans;
    for(int i=14;i>=0;--i)
        if(fa[x][i].first!=fa[y][i].first)
            ans=min(ans,min(fa[x][i].second,fa[y][i].second)),
            x=fa[x][i].first,
            y=fa[y][i].first;
    return min(ans,min(fa[x][0].second,fa[y][0].second));
}

signed main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=m;++i)
    {
        int x,y,w;
        scanf("%lld%lld%lld",&x,&y,&w);
        map[x].push_back({y,w});
        map[y].push_back({x,w});
    }
    kruskal();
    bool flag[N]={};
    for(int i=1;i<=n;++i)
        if(!flag[find(i)])
            init(find(i),0,0),
            flag[find(i)]=1;
    int T;
    scanf("%lld",&T);
    while(T--)
    {
        int x,y;
        scanf("%lld%lld",&x,&y);
        printf("%lld\n",len(x,y));
    }
    return 0;
}
  • 写回答

2条回答 默认 最新

  • 阿里嘎多学长 2024-05-30 12:41
    关注

    以下内容由CHATGPT及阿里嘎多学长共同生成、有用望采纳:


    根据您提供的代码和描述,您正在解决一个图论问题,具体是使用Kruskal算法来找到最小生成树,并且使用树上倍增技术来快速查询两点之间的最短路径。您的代码中有几个潜在的问题点,我会逐一指出并提供一些建议:

    1. 数据类型: 您的代码中使用了long long作为基本数据类型,这是好的实践,因为图论问题中的数据量可能会很大。

    2. Kruskal算法: 您的Kruskal算法实现看起来是正确的。您正确地使用了并查集来确保不会添加到环中。

    3. 树上倍增: 您的树上倍增实现看起来也是正确的。您已经初始化了fa数组,并在递归调用init函数时填充了它。

    4. 并查集的初始化: 您的并查集初始化似乎是正确的,但是您没有提供一个函数来初始化并查集,这可能会导致问题。通常,您需要一个函数来初始化每个节点的根节点为它自己。

    5. 错误处理: 在len函数中,您检查了find(x)find(y)是否为真,这是好的,但是您应该检查find(x) != find(y),而不是&&。逻辑运算符使用错误可能会导致错误的结果。

    6. 测试点信息: 您提供了测试点信息的截图,但是没有提供具体内容。测试点信息对于调试代码非常重要,因为它可以帮助您理解代码在特定输入下的表现。如果您能够提供测试点的具体内容,我可以更具体地帮助您。

    7. 代码风格: 您的代码风格是一致的,这是好的。但是,请注意,main函数的返回类型应该是int,而不是signed

    8. 代码注释: 您的代码中缺少注释,这可能会使调试变得更加困难。添加注释可以帮助您和其他人更好地理解代码的意图。

    9. 输入处理: 您的代码中使用了scanf来处理输入,这是C++中常见的做法。但是,您可能需要确保输入格式与题目要求相匹配。

    10. 错误消息: 如果您的代码在某些测试点上失败,您可能需要检查错误消息来确定问题所在。例如,RE通常表示运行时错误,而WA表示答案错误。

    由于我没有测试点的具体内容,我无法提供更具体的调试建议。如果您能够提供测试点的具体内容,我将能够更准确地帮助您找到问题所在。

    至于参考资料,您可以查看以下资源:

    希望这些建议对您有所帮助!如果您有更多问题或需要进一步的帮助,请提供更多信息。

    评论 编辑记录

报告相同问题?

问题事件

  • 修改了问题 5月30日
  • 创建了问题 5月30日