zoukankan      html  css  js  c++  java
  • [CF1343E] Weights Distributing

    Description

    给定无向图和一个权值多重集,用它给无向图分配边权,要求是全排列,求路径 (a o b o c) 最短长度。

    Solution

    考虑到 (a o b)(b o c) 可能有一段重复的 (b - d),枚举 (d),这样只需求出 (a o d, d o b, b o d, d o c) 的最小值

    设对某个 (d)(a-d,b-d,c-d) 长度分别为 (x,y,z),则我们会将最小的 (y) 个边权分配给 (b-d),剩余中最小的 (x+z) 个分配给 (a-d,c-d),因此可以在 (O(1)) 中计算出长度,故时间复杂度为 (O(n))

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    const int N = 200005;
    const int dbg = 0;
    
    vector <int> g[N];
    int p[N],dis[3][N],vis[N],t1,t2,n,m,a,b,c;
    
    void bfs(int v0,int id)
    {
        queue <int> que;
        que.push(v0);
        dis[id][v0]=0;
        while(!que.empty())
        {
            int p=que.front();
            que.pop();
            for(int q:g[p])
            {
                if(dis[id][q]>dis[id][p]+1)
                {
                    dis[id][q]=dis[id][p]+1;
                    que.push(q);
                }
            }
        }
    }
    
    void solve()
    {
        cin>>n>>m>>a>>b>>c;
        for(int i=1;i<=m;i++)
        {
            cin>>p[i];
        }
        for(int i=1;i<=m;i++)
        {
            cin>>t1>>t2;
            g[t1].push_back(t2);
            g[t2].push_back(t1);
        }
        for(int i=1;i<=n;i++)
        {
            dis[0][i]=dis[1][i]=dis[2][i]=1e9;
        }
        dis[0][a]=dis[1][b]=dis[2][c]=0;
        for(int i=1;i<=n;i++)
        {
            vis[i]=0;
        }
        bfs(a,0);
        for(int i=1;i<=n;i++)
        {
            vis[i]=0;
        }
        bfs(b,1);
        for(int i=1;i<=n;i++)
        {
            vis[i]=0;
        }
        bfs(c,2);
        sort(p+1,p+m+1);
        int ans=1e18;
        int *da=dis[0],*db=dis[1],*dc=dis[2];
        for(int i=1;i<=m;i++)
        {
            p[i]+=p[i-1];
        }
        if(dbg)
        {
            cout<<"sum seq: ";
            for(int i=1;i<=m;i++)
            {
                cout<<p[i]<<" ";
            }
            cout<<endl;
        }
        int *sum=p;
        for(int i=1;i<=n;i++)
        {
            int x=da[i],y=db[i],z=dc[i];
            if(dbg)
            {
                cout<<" i="<<i<<" x,y,z="<<x<<y<<z<<endl;
            }
            if(x+y+z>m) continue;
            int tmp=0;
            tmp+=sum[x+y+z]+sum[y];
            if(dbg)
            {
                cout<<"  "<<sum[x+y+z]<<"+"<<sum[y]<<"="<<tmp<<endl;
            }
            ans=min(ans,tmp);
        }
        cout<<ans<<endl;
        for(int i=1;i<=n;i++)
        {
            g[i].clear();
            p[i]=0;
        }
    }
    
    signed main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            solve();
        }
    }
    
    
  • 相关阅读:
    打砖块代码解析
    C语言拾遗(一):整型提升
    高性能分布式计算与存储系统设计概要——暨2012年工作3年半总结(下) <转>
    c10k测试:每连接新线程回显服务器(echo server) (转)
    高性能分布式计算与存储系统设计概要——暨2012年工作3年半总结(上) <转>
    java基础总结equals与==
    Java的运行机制概括
    Java 基础总结反射的基本操作
    python爬取基础网页图片
    px,dp,sp以及像素密度
  • 原文地址:https://www.cnblogs.com/mollnn/p/13594381.html
Copyright © 2011-2022 走看看