hdu5876 Sparse Graph

本文介绍了一种解决补图单源最短路径问题的方法,利用BFS思想结合两个set进行迭代,实现O(m+n)的时间复杂度。通过不断交换set来更新未处理和已处理节点的状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:给2e6的点,2e5的边,求补图中,单源点到所有点的最短路

题解:比赛时候,没有仔细考虑这个,发现其实挺水的

            边少的,一半是用bfs

            维护两个set,set1中,记录的是,没有处理的点,set2中是刚刚处理的点

            经过一个点时,把连接的点,且在set1中的点,放到set2中,然后set1中的点就可以处理,交换set1和set2

             时间复杂度O(m+n)(比赛时候错误的估计了复杂度。。)

queue <int> q;
set <int> s;
set <int> s1;
int ans[200010];
set <int> ss[200010];

int main(){
    int t;
    cin>>t;
    while(t--){
        while(!q.empty())
            q.pop();
        s.clear();
        for(int i=0;i<200002;i++)
            ss[i].clear();
        int n,m;
        scanf("%d %d",&n,&m);
        int x,y;
        for(int i=0;i<m;i++){
            scanf("%d %d",&x,&y);
            ss[x].insert(y);
            ss[y].insert(x);
        }
        int beg=0;
        cin>>beg;
        for(int i=1;i<=n;i++){
            if(i!=beg){
                s.insert(i);
            }
        }
        memset(ans,-1,sizeof(ans));
        ans[beg]=0;
        q.push(beg);
        while(!q.empty()){
            int xx=q.front();
            q.pop();
            for(set <int>::iterator it=ss[xx].begin();it!=ss[xx].end();it++){
                if(s.count(*it)!=0){
                    s.erase(*it);
                    s1.insert(*it);
                }
            }
            for(set <int>::iterator it=s.begin();it!=s.end();it++){
                ans[*it]=ans[xx]+1;
                q.push(*it);
            }
            s.swap(s1);
            s1.clear();
        }
        bool bool1=true;
        for(int i=1;i<=n;i++){
            if(i!=beg){
                if(bool1){
                    bool1=false;
                    printf("%d",ans[i]);
                }
                else {
                    printf(" %d",ans[i]);
                }
            }
        }
        cout<<endl;
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值