ZOJ - 2027 【Dijkstra + 去掉每条路径上权值最大的边后的最短路】

Description
Samball is going to travel in the coming vacation. Now it's time to make a plan. After choosing the destination city, the next step is to determine the travel route. As this poor guy has just experienced a tragic lost of money, he really has limited amount of money to spend. He wants to find the most costless route. Samball has just learned that the travel company will carry out a discount strategy during the vacation: the most expensive flight connecting two cities along the route will be free. This is really a big news.
Now given the source and destination cities, and the costs of all the flights, you are to calculate the minimum cost. It is assumed that the flights Samball selects will not have any cycles and the destination is reachable from the source.
 
Input
 
The input contains several test cases, each begins with a line containing names of the source city and the destination city. The next line contains an integer m (<=100), the number of flights, and then m lines follow, each contains names of the source city and the destination city of the flight and the corresponding cost. City names are composed of not more than 10 uppercase letters. Costs are integers between 0 to 10000 inclusively.
 
Process to the end of file.
 
Output
 
For each test case, output the minimum cost in a single line.
 
Sample Input
HANGZHOU BEIJING
2
HANGZHOU SHANGHAI 100
SHANGHAI BEIJING 200
 
Sample Output
100
 
 
题意:
  小明去旅行,选择路径,将他选择的路径中的权值最大的一条边去掉,然后判断在去掉了最大权值边的这些路径中,路径最短的是多少
  数据第一行给的是,地图的起始点终点,接下来的一行表示边的条数,    
 
  另外一个需要注意的是:
将 string 字符串转化为 数字,计算方便
 
思路:
  建立一个 MAX 数组 存放每条路径上的权值最大的边,然后直接用 Dijkstra 算法计算即可。
 
 
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <cmath>
#define LL long long
#define INF 0x3f3f3f3f
#define MOD 1000000007
#define maxn 3010
#define Pair pair<int, int>
#define mem(a, b) memset(a, b, sizeof(a))
const float PI = acos(-1.0);

using namespace std;

const int N = 105;
map <string, int> city;
int m, cnt, tot, dis[N], head[N];
//MAX 数组记录最大边
int MAX[N];
//数组模拟邻接表
struct Edge {
    int to, cost;
    int next;
}edge[N];

//将字符串返回一个代表该字符串的数字
int Hash(string &s)
{
    if(!city.count(s)) {
        city[s] = cnt++;
    }
    return city[s];
}

void add(int u, int v, int w)
{
    edge[tot].to = v; edge[tot].cost = w;
    edge[tot].next = head[u]; head[u] = tot++;
}

void Dijkstra(int st)
{
    priority_queue <Pair,vector<Pair>,greater<Pair> > Q;
    mem(dis, 0x3f);
    mem(MAX, 0);
    dis[st] = 0;
    Q.push(Pair(0,st));
    while(!Q.empty()) {
        Pair t = Q.top(); Q.pop();
        int u = t.second;
        if(dis[u] > t.first) continue;
        for(int i = head[u]; i != -1; i = edge[i].next) {
            int v = edge[i].to;
            int w = edge[i].cost;
            int tmp ;

            //最大值边的处理方案
            if(MAX[u] < w) {
                tmp = dis[u] + MAX[u];
                MAX[v] = w;
            } else {
                tmp = dis[u] + w;
                MAX[v] = MAX[u];
            }

            if(dis[v] > tmp) {
                dis[v] = tmp;
                Q.push(Pair(tmp,v));
            }
        }
    }
}

int main()
{
    string s1, s2;
    int cnt = 0;
    while(cin >> s1 >> s2) {
        int st = Hash(s1), ed = Hash(s2);
        enf = ed;
        memset(head, -1, sizeof(head));
        tot = 0;
        scanf("%d", &m);
        int u, v, w;
        for(int i = 0; i < m; i++) {
            cin >> s1 >> s2;
            u = Hash(s1); v = Hash(s2);
            scanf("%d", &w);
            add(u, v, w);
        }
        Dijkstra(st);
        printf("%d\n", ans);
    }
    return 0;
}

 

重点核心:
if(MAX[u] < w) {
  tmp = dis[u] + MAX[u];
  MAX[v]
= w; } else {   tmp = dis[u] + w;   MAX[v] = MAX[u]; } 如果当前的路径权值大于之前保存的该路径上的最大权值,该两点的权值保存在MAX数组中 然后将之前保存在 MAX数组中的 最大权值还给 dis【PS:如果将某边加入到 MAX_EDGE数组中的话,该边就不会加入到 dis 数组中】 那么现在看来 dis数组中记录的只有 1点到 i 点的 ,并且不包含该路径中权重最大的路径的最短路径
 
 
posted @ 2017-04-22 21:58  渣渣技术狗  阅读(94)  评论(0)    收藏  举报