• 魔法宝石(邻接表+dfs更新)


    魔法宝石
    Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
    Total Submission(s): 254 Accepted Submission(s): 85

    Problem Description
    小s想要创造n种魔法宝石。小s可以用ai的魔力值创造一棵第i种魔法宝石,或是使用两个宝石合成另一种宝石(不消耗魔力值)。请你帮小s算出合成某种宝石的所需的最小花费。

    Input
    第一行为数据组数T(1≤T≤3)。
    对于每组数据,首先一行为n,m(1≤n,m≤10^5)。分别表示魔法宝石种类数和合成魔法的数量。
    之后一行n个数表示a1到an。(1≤ai≤10^9)。ai表示合成第i种宝石所需的魔力值。
    之后m行,每行三个数a,b,c(1≤a,b,c≤n),表示一个第a种宝石和第b种宝石,可以合成一个第c种宝石。

    Output
    每组数据输出一行n个数,其中第i个数表示合成第i种宝石的魔力值最小花费。

    Sample Input

    1
    3 1
    1 1 10
    1 2 3

    Sample Output

    1 1 2

    题意

    分析

    由于一个宝石费用减少只会影响以它直接/间接为材料的宝石,故我们先根据宝石关系建邻接表,每次遇到有宝石费用减少,dfs处理一遍即可
    题目不错,多复习

    trick

    似乎时间复杂度略高,数据较弱?

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    #define ll long long
    #define F(i,a,b) for(int i=a;i<=b;++i)
    #define R(i,a,b) for(int i=a;i<b;++i)
    #define mem(a,b) memset(a,b,sizeof(a))
    
    struct node
    {
        int x,y,z;
    }data[100100];
    vector<node>mp[100100];
    int a[100100];
    
    void dfs(int z)
    {
        node temp;
        for(int j=0;j<mp[z].size();j++)//每次找与z直接关联的点更新
        {
            temp=mp[z][j];
            if(a[temp.z]>a[temp.x]+a[temp.y])
            {
                a[temp.z]=a[temp.x]+a[temp.y];
                dfs(temp.z);
            }
        }
    }
    int main()
    {
        int t;
        for(scanf("%d",&t);t--;)
        {
            int n,m;
            mem(mp,0);
            mem(a,0);
            mem(data,0);
            scanf("%d %d",&n,&m);
            for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
            int x,y,z;
            for(int i=0;i<m;i++)
            {
                scanf("%d %d %d",&x,&y,&z);
                data[i]={x,y,z};
                node temp;
                temp.x=x,temp.y=y,temp.z=z;
                mp[x].push_back(temp);//建双向边
                temp.x=y,temp.y=x;
                mp[y].push_back(temp);
                
            }
            for(int i=0;i<m;i++)
            {
                x=data[i].x,y=data[i].y,z=data[i].z;
                if(a[z]>a[x]+a[y])
                {
                    a[z]=a[x]+a[y];
                    dfs(z);
                }
            }
            for(int i=1;i<=n;++i)printf("%d%c",a[i],i==n?'
    ':' ');
        }
        return 0;
    } 
    
  • 相关阅读:
    Liunx用户运行模式
    指令——ps -ef
    文本编辑器vim/vi——末行模式
    文本编辑器vim/vi——模式切换及输入模式
    pandas中Dataframe的查询方法([], loc, iloc, at, iat, ix)
    Python的numpy库中rand(),randn(),randint(),random_integers()的使用
    python常见面试题
    读取gzmt.csv文件,计算均值及概率
    NumPy数组对象
    写一个带文本菜单的程序,菜单项如下 (1) 取五个数的和 (2) 取五个数的平均值 (X) 退出。
  • 原文地址:https://www.cnblogs.com/chendl111/p/7125567.html
Copyright © 2020-2023  润新知