Silver Cow Party Currency Exchange

Silver Cow Party

题目

Silver Cow Party
德平在他的农场里养了n头牛,每头牛都有一个固定的位置,每天这些牛都要到德平家里参加聚会然后回去,给出n,m,代表牛数+1和有向边数,接着是m条有向边(a,b,c),代表从牛a到牛b需要花费c秒,给你德平家的位置X(1~n的除x外的编号为牛的位置),每头牛都有一个参加聚会并且回到原来位置的最短时间,从这些最短时间里找出一个最大值输出 N<=1000,M<=100,000,c<=100

Line 1: 三个整数分别代表: NM, and X
Lines 2.. M+1: Line i+1 代表道路i的三个整数:a,b,c
表示从a到b需要c时间,(不能表示从b到a的时间为c)

Line 1: 所有 牛最短时间里找出一个 最大值输出

牛1:去4s,回1s,共5s
牛3:去6s,回3s,共9s
牛4:去3s,回7s,共10s

input

4 8 2
1 2 4
1 3 2
1 4 7
2 1 1
2 3 5
3 1 2
3 4 4
4 2 3

output

10

思路

有n个节点, 其中一个节点是要去到的终点x。
在除x之外的节点中, 找到一个节点, 它去到x点的最短距离 + 从x点回来的最短距离, 之和的最大值。

我们可以求出所有点到x和x到所有点的最短距离, 然后遍历一遍结果求出最大值。

dijkstra可以求出从起点开始到所有点的最短路径, 模板是求从起点到终点, 这里把x点当做起点即可求出x到所有点的距离。
至于所有点到x的距离, 可以将所有的有向边反转方向, 再求一次dijkstra便是所有点到x的最短距离。

代码

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

using namespace std;

//------- Coding Area ---------//
const int N = 1e3 + 10, INF = 0x3f3f3f3f;

int n, m, x;
int dist[N], g[N][N];
int d1[N], d2[N];
bool st[N];
void dijkstra()
{
    memset(dist, INF, sizeof dist);
    memset(st, 0, sizeof st);
    dist[x] = 0;
    for (int i = 1; i <= n; i++)
    {
        int t = -1;
        for (int j = 1; j <= n; j++)
            if (!st[j] && (t == -1 || dist[j] < dist[t]))
                t = j;
        st[t] = true;
        for (int j = 1; j <= n; j++)
            dist[j] = min(dist[j], dist[t] + g[t][j]);
    }
}

int main()
{
    cin.tie(0)->sync_with_stdio(false);
    cin >> n >> m >> x;
    memset(g, INF, sizeof g);
    while (m--)
    {
        int a, b, c;
        cin >> a >> b >> c;
        g[a][b] = min(g[a][b], c);
    }
    // 第一次
    dijkstra();
    memcpy(d1, dist, sizeof dist);
    for (int i = 1; i <= n; i++)
    {
        for (int j = i + 1; j <= n; j++)
            swap(g[i][j], g[j][i]);
    }
    // 第二次
    dijkstra();
    memcpy(d2, dist, sizeof dist);
    int res = 0;
    for (int i = 1; i <= n; i++)
        res = max(d1[i] + d2[i], res);
    cout << res << endl;

    return 0 ;
}

Currency Exchange

Currency Exchange

题目

太长就不贴了。

思路

大致是有没有一种情况, 币A 换到 币B, 然后币B换到币A, 最后总数比刚开始还多。
即 A->B 增加, B->A也增加, 显然是存在一个环路, 负环问题。正常的负环问题会导致最短最优路径为在环中循环, 使权值一直减少, 这里则是使权值一直增加。

计算两点之间的距离, 为 (上一点的币数 - 手续费) * 汇率, 也就是(dist[t] - cost[i]) * rate[i]

代码

//#include "D:\Network_Computer_Scurity\Coding\OnlineJudgeProblem\Problems\Algorithm\aze.h"
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
//------- Coding Area ---------//
const int N = 1e3 + 111, M = N;

double v;
int n, m, s;
int h[N], e[M], ne[M], idx;
double dist[N], r[M], c[M]; // 汇率和手续
bool st[N];
int cnt[N];

bool spfa()
{
    queue<int> q;
    q.push(s);
    dist[s] = v;
    st[s] = true;
    while (!q.empty())
    {
        int t = q.front();
        q.pop();
        st[t] = false;
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];
            if (dist[j] < (dist[t] - c[i]) * r[i])
            {
                dist[j] = (dist[t] - c[i]) * r[i];
                cnt[j] = cnt[t] + 1;
                if (cnt[j] >= n)
                    return true;
                if (!st[j])
                {
                    q.push(j);
                    st[j] = true;
                }
            }
        }
    }
    return false;
}

void add(int a, int b, double R, double C)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx;
    r[idx] = R, c[idx] = C;
    idx++;
}

int main()
{
    cin.tie(0)->sync_with_stdio(false);
    cin >> n >> m >> s >> v;
    memset(h, -1, sizeof h);

    while (m--)
    {
        int a, b;
        double ra, ca, rb, cb;
        cin >> a >> b >> ra >> ca >> rb >> cb;
        add(a, b, ra, ca);
        add(b, a, rb, cb);
    }
    if (spfa())
        cout << "YES\n";
    else
        cout << "NO\n";

    return 0;
}
posted @ 2022-08-12 12:55  EdwinAze  阅读(31)  评论(0编辑  收藏  举报