FJUT 3930 最短路径

上文说到moxin跟郭先生去看电影了,于是moxin又双叒破产了,无奈之下moxin只能又做起了卖菜的生意

当然卖菜就得进货,于是moxin就去进货了,这里的商店比较奇葩,遵守以下规则:

1.当两种不同的菜有着相同的价值的时候,那么可以进行交换(比如a种菜的价值等于b种菜的价值,那么a种菜可以与b种菜互相交换,互相交换是不需要花费额外的价值)

2.可以通过讨价还价,以一种菜的价值 + x价值RMB 来换取另一种菜

3.可以直接使用等于菜的价值RMB来购买一种菜

那么问题来了,moxin想要知道购买每一种菜最少需要花费多少RMB?

Input
第一行输入T(1<=T<=10),代表有T组

第二行输入n,m(2<=n<=1e3, 0<=m<=1e3)

代表有n种菜,m种讨价还价的关系

接下来n行,每行有两个整数a,b(1<=a<=n, 1<=b<=1e5)

代表n种菜,第a种菜的价值为b

接下来m行,每行有三个整数a,b,c(1<=a<=n, 1<=b<=n, 1<=c<=1e5, a != b)

代表a种菜+价值为c的RMB可以换取b种菜

(数据一共7组)

Output
n行

每行只有一个整数,每行的整数代表对应的第i种菜所需的最小花费

SampleInput
1
3 1
1 7
2 2
3 2
1 3 1
SampleOutput
7
2
2

题意:可以通过三种途径来使得获得某种菜的价值更小,求获得全部菜的最小花费
思路:思维最短路径好题 根据每种菜之间的关系建图然后跑dijstra得到答案 ,较难的点在于建图 具体看代码注释
一开始没看范围暴力手搓Floyd然后就赠送了我衣个大大的TLE

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cstdio>

using namespace std;
typedef pair<int,int> p;

const int maxn=1e3+5;
const int inf=0x3f3f3f3f;
int n,m;

struct edge
{
    int to;
    int cost;
    edge(int tt,int cc):to(tt),cost(cc){}
};

int dist[maxn];
int vis[maxn];

vector<edge>g[maxn];


void dj(int s)///di就不多说了 套板子就行
{
    fill(dist,dist+n+1,inf);
    priority_queue<p,vector<p>,greater<p> >que;

    dist[s]=0;
    que.push(p(0,s));

    while(!que.empty())
    {
        p now=que.top();
        que.pop();

        int temp=now.second;

        if(now.first>dist[temp])
            continue;

        for(int i=0; i<g[temp].size(); i++)
        {
            edge next=g[temp][i];

            if(dist[next.to]>dist[temp]+next.cost)
            {
                dist[next.to]=dist[temp]+(int)next.cost;

                que.push(p(dist[next.to],next.to));
            }
        }
    }
}


int main()
{
    int t;

    scanf("%d",&t);

    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(vis,0,sizeof(vis));///初始化

        for(int i=0; i<=n; ++i)
            g[i].clear();


        int a,b,c;

        for(int i=0; i<n; ++i)
        {
            scanf("%d%d",&a,&b);
            vis[a]=b;
            g[0].push_back(edge(a,b));///a种菜的价值为b
        }

        for(int i=0; i<m; ++i)
        {
            scanf("%d%d%d",&a,&b,&c);
            g[a].push_back(edge(b,c));///可以通过a种菜的花费c元得到b种菜
        }

        for(int i=1; i<=maxn; ++i)
        {
            for(int j=1; j<=maxn; ++j)
            {
                if(vis[i]!=0 && i!=j &&vis[i]==vis[j])///不同的菜有相同的价值是可以互换,那就在相同价值的a,b两种菜之间建立一条权值为0的边
                {
                    g[i].push_back(edge(j,0));
                    g[j].push_back(edge(i,0));
                }
            }
        }

        dj(0);

        for(int i=1; i<maxn; ++i)///输出即可
        {
            if(vis[i])
                printf("%d\n",dist[i]);
        }
    }
    return 0;
}
发布了54 篇原创文章 · 获赞 0 · 访问量 1219

猜你喜欢

转载自blog.csdn.net/weixin_44144278/article/details/100025553