zoukankan      html  css  js  c++  java
  • CF1343E-Weights Distributing (最短路)

    题目大意:

    给定你一个由n个节点,m条边组成的图,再告诉你3个节点a,b,c和一个大小为m的数组p,

    让你将p[i]赋值给每条边,使得a->b->c的路径长度最短。

    链接:https://codeforces.com/contest/1343/problem/E

    思路:

    因为要使路径长度最短,所以边权要尽量小,所以我们先将p数组进行排序,然后预处理出他们的前缀和,

    然后我们分别求出每个点到a的最短距离dis1[i],每个点到b的最短距离dis2[i],每个点到c的最短距离dis3[i],

    我们发现a->b->c要么通过一个中间点,要么是一条直线,而第二种情况即中间点为b,因为dis2[i]存在重复,

    所以我们将权值最小的p[i]赋给b->i之间的路径,剩下的路径再依次从小到大赋值,然后我们枚举每个点i,找到最小值即可。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int MAXN=2e5+5;
    const ll INF=1e18+8;
    ll p[MAXN],sum[MAXN];
    struct node
    {
        int to,nxt;
    }e[MAXN<<1];
    int head[MAXN],tot,n,m,a,b,c;
    void add(int x,int y)
    {
        e[tot].to=y;e[tot].nxt=head[x];head[x]=tot++;
    }
    void add_edge(int x,int y)
    {
        add(x,y);add(y,x);
    }
    ll dis1[MAXN],dis2[MAXN],dis3[MAXN];
    void bfs(int s,ll *dis)
    {
        queue<int>q;
        q.push(s);dis[s]=0;
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=head[u];~i;i=e[i].nxt)
            {
                int v=e[i].to;
                if(!dis[v]&&v!=s)
                {
                    dis[v]=dis[u]+1;q.push(v);
                }
            }
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);cin.tie(0);
        int t;cin>>t;
        while(t--)
        {
            memset(head,-1,sizeof(head));tot=0;
            for(int i=0;i<=n;i++)
                dis1[i]=0,dis2[i]=0,dis3[i]=0;
            cin>>n>>m>>a>>b>>c;
            for(int i=1;i<=m;i++)
            {
                cin>>p[i];
            }
            for(int i=1;i<=m;i++)
            {
                int x,y;cin>>x>>y;add_edge(x,y);
            }
            sort(p+1,p+1+m);
            for(int i=1;i<=m;i++)
            {
                sum[i]=sum[i-1]+p[i];
            }
            bfs(a,dis1);bfs(b,dis2);bfs(c,dis3);
            ll ans=INF;
            for(int i=1;i<=n;i++)
            {
                if(dis1[i]+dis3[i]+dis2[i]<=m)
                {
                    ans=min(ans,sum[dis1[i]+dis3[i]+dis2[i]]+sum[dis2[i]]);
                }
            }
            cout<<ans<<endl;
        }
        return 0;
    }
  • 相关阅读:
    Document
    Document
    Document
    Document
    Document
    Document
    set常见操作:
    select 不存在字段,并设置默认值
    c#为字段设置默认值,以及构造函数初始化List对象。
    ThreadLocal
  • 原文地址:https://www.cnblogs.com/ljxdtc666/p/12812488.html
Copyright © 2011-2022 走看看