uva 10457 Magic Car (图论好题)

该问题描述了一种寻找无向图中两个顶点之间路径的方法,目标是使最大边权与最小边权之差尽可能小。尝试了最短路和二分搜索等方法未成功,最终通过贪心策略解决,采用 Kruskal 算法思想,按边权从小到大枚举,直至找到联通两点的路径,将复杂度降低到 O(m^2)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Problem E

Magic Car

Input: standard input

Output: standard output

Time Limit: 5 seconds

 

ACM ( Association of Car Modernization) has recently developed a new car, "MAGIC CAR". It uses solar energy. The car has some interesting characteristics : 

  • It uses up constant amount of energy at the start for any initial speed.

  • It also uses up constant energy when stops.

  • If it changes speed to a value which is less than already achieved least speed or greater than already achieved most speed, it uses up some energy. In both cases the energy is equal to the absolute difference of the current speed and previously achieved least or most speed.

  • The loss of energy does not depend on the distance the car covered (Really magic!!!).

    Mr. Oberoy has such a magic car. So far he has used the car quite intelligently so that minimum energy is used up. This was easy for him as he could take any speed on any road. But recently, TCD(Transport Control Department) has decided that there will be a fixed speed for each road in the city and everybody must maintain the speed. Mr. Oberoy is in problem now. Can you help him so that he can optimally use the car ?

    Input

    Each dataset starts with two positive integer, N (2<=N<=200) denoting the number of junctions and M (1<=M<=1000) denoting the number of roads in Mr. Oberoy's city. Each junction is identified by a unique integer from 1 to N. In next few lines there will be road descriptions. A road is described by three positive integers which are start, end junctions and the fixed speed of that road. There may be more than one roads between two junctions. Roads are bidirectional. In the next line there will be two positive integers which are the used up energy during start and stop of the magic car. Next line will contain an integer K (1<=K<=5) indicating the number of queries. Each of following K lines will contain two integers, the source and destination junction of Mr. Oberoy. Source and destination will not be same. Input is terminated by EOF.


    Output

    For each dataset print the minimum possible used up energy for each query of Mr. Oberoy. It is guranteed that the destination is always reachable from source.

     

    Sample Input

    4 41 2 22 3 41 4 13 4 25 521 31 2

    Sample Output

    1110

Author : Md. Kamruzzaman

The Real Programmers' Contest-2

求无向图中两个顶点的路径,使得最大边权和最小边权之差尽量小。首先想到的是,固定最小边权(或最大边权),用最短路的方法,求在最小边权条件下,对应的最小的最大边权,超时。。然后改成固定最小边权,二分枚举最大边权,判断条件下两点是否联通,用bfs判断超时,改成并查集判断,超时。。简直要崩溃了。。然后想到贪心,其实不用二分枚举。在一个图中求两点间的一条路径,使得边权最大最小,可以用krukal的思想,边权排序后,从小向大枚举,直到两点联通。这样复杂度就可以降到m^2了。

#include<cstdio>
#include<map>
#include<queue>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<list>
#include<set>
#include<cmath>
using namespace std;
const int maxn = 200 + 5;
const int maxm = 1000 + 5;
const int INF = 1000000000;
const double eps = 1e-6;
typedef unsigned long long ULL;
typedef long long LL;
typedef pair<int, int> P;
#define fi first
#define se second

int n, m;
struct Edge{
    int x, y, v;
    Edge(){}
    Edge(int x, int y, int v){
        this -> x = x;
        this -> y = y;
        this -> v = v;
    }
    bool operator < (const Edge& e) const{
        return v < e.v;
    }
}edge[maxm];

int fa[maxn];
int Find(int x){return x==fa[x]?x:fa[x]=Find(fa[x]);}

int solve(int source, int sink){
    sort(edge, edge+m);
    int ret = INF;
    for(int i = 0;i < m;i++){
        int maxv = edge[i].v;
        for(int j = 1;j <= n;j++)
            fa[j] = j;
        for(int j = m-1;j >= 0;j--){
            int x = edge[j].x;
            int y = edge[j].y;
            int v = edge[j].v;
            if(v <= maxv){
                int X = Find(x);
                int Y = Find(y);
                fa[X] = Y;
                if(Find(source)==Find(sink)){
                    ret = min(ret, maxv-v);
                    break;
                }
            }
        }
    }
    return ret;
}

int main(){
    while(scanf("%d%d", &n, &m) != EOF){
        for(int i = 0;i < m;i++){
            int x, y, v;
            scanf("%d%d%d", &x, &y, &v);
            edge[i] = Edge(x, y, v);
        }
        int tem1, tem2;
        scanf("%d%d", &tem1, &tem2);
        int q;
        scanf("%d", &q);
        while(q--){
            int source, sink;
            scanf("%d%d", &source, &sink);
            printf("%d\n", tem1 + tem2 + solve(source, sink));
        }
    }
    return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值