codeforces-1343E(贪心+BFS)

Weights Distributing

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

题目描述:

给定n个点m条无向边,再给你a,b,c三个点和m个值,现在要求你将这m个值分配这m条边,使a->b->c的路径的权值最小

思路:

分类讨论,一种情况是a->b和b->c这两条路上无交点,这样直接将权值排序后取最小即可,第二种就是两条路上有交点,这时候我们一定可以找到一个交点x,该交点把路径分为a->x,x->b,b->x,x->c这四段路线,因为b->x和x->b本质上是同一条路,所以我们需要优先把较小的权值分配给这条路,可以先用bfs求出a、b、c三个点到所有点的单位距离,接着贪心赋值即可。

代码:

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int INF = 0x3f3f3f3f;
const ll N = 1e6;
const double PI = acos(-1.0);
#define Test ll tesnum;tesnum = read();while(tesnum--)
ll read();
ll val[N];
vector<int> g[N];
void bfs(int id,vector<int> &v)
{
    v[id] = 0;
    queue<int> q;
    q.push(id);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        for(int nx:g[u]){
            if(v[nx]==INF){
                v[nx] = v[u]+1;
                q.push(nx);
            }
        }
    }
}
int main()
{
    Test{
        int n,m,a,b,c;
        cin>>n>>m>>a>>b>>c;
        for(int i = 1; i <= m; i++){
            cin>>val[i];
        }
        for(int i = 1; i <= n; i++)g[i].clear();
        sort(val+1,val+1+m);
        for(int i = 1; i <= m; i++){
            int u,v;
            cin>>u>>v;
            g[u].push_back(v);
            g[v].push_back(u);
            val[i] += val[i-1];
        }
        vector<int> disa(n+1,INF);
        vector<int> disb(n+1,INF);
        vector<int> disc(n+1,INF);
        bfs(a,disa);
        bfs(b,disb);
        bfs(c,disc);
        ll ans  = 2e16;
        for(int i = 1; i <= n; i++){
            if(disa[i]+disb[i]+disc[i]>m)continue;
            ans = min(ans,val[disb[i]]+val[disa[i]+disb[i]+disc[i]]);
        }
        cout<<ans<<endl;
    };
    return "BT7274", NULL;
}

inline ll read() {
    ll hcy = 0, dia = 1;char boluo = getchar();
    while (!isdigit(boluo)) {if (boluo == '-')dia = -1;boluo = getchar();}
    while (isdigit(boluo)) {hcy = hcy * 10 + boluo - '0';boluo = getchar();}
    return hcy * dia;
}
posted @ 2020-07-26 22:34  BT-7274  阅读(170)  评论(0编辑  收藏  举报