PAT A1003 Emergency(25 分)----最短路径

总结:这道题坑的地方在于求最大集结救援队是值得一条最短路线上的所有节点之和,而不是所有最短路径上的节点之和

深搜(dfs):

1.求路径,点权,边权。遍历,最大连通子图。

2.两段代码分别使用深搜和dijkstra算法解决的,有兴趣可以两端都看看,第二段代码比第一段快,递归程序消耗大。

dijkstra算法相当于非递归版的广度搜索。

代码:

#include<iostream>
#include<vector>
#include<map>
#include<set>
using namespace std;
int G[600][600];       //边权
int weight[600];       //点权
int vi[600];
int minlen = 999999;
int totalen = 0;
map<int,vector<vector<int>>> so;
int n, m, c1, c2;
void dfs(int index, vector<int> road)
{
    if (vi[index])return;
    if (index == c2)
    {
        if (totalen <= minlen){ minlen = totalen;  so[minlen].push_back(road); }
        return;
    }
    vi[index] = 1;
    for (int i = 0; i <n; i++)
    {
        if ((!vi[i]) && (G[index][i]))
        {
            if (totalen + G[index][i]>minlen)continue;
            totalen += G[index][i];
            road.push_back(i);
            dfs(i, road);
            totalen -= G[index][i];
            road.pop_back(); vi[i] = 0;
        }
    }
}
int main()
{
    cin >> n >> m >> c1 >> c2;
    for (int i = 0; i <n; i++)
    {
        int wt; scanf("%d", &wt);
        weight[i] = wt;
    }
    for (int i = 0; i < m; i++)
    {
        int a, b, ti;
        scanf("%d%d%d", &a, &b, &ti);
        G[a][b] = ti; G[b][a] = ti;
    }
    vector<int> road;
    road.push_back(c1);
    dfs(c1, road);
    int sum = 0; int total;
    for (int i = 0; i < so[minlen].size(); i++){
        total = 0;
        for (int j = 0; j < so[minlen][i].size(); j++)
        {
            total+=weight[so[minlen][i][j]];
        }
        if (total>sum)sum = total;
    }
    cout << so[minlen].size()<<" "<<sum;
    return 0;
}

代码2:

dijkstra算法:

#include<iostream>
#include<vector>
#include<map>
#include<set>
using namespace std;
int G[600][600];       //边权
int weight[600];       //点权
int num[600];       //最短路径条数
int dis[600];         //起点到i的最短路径
int w[600];              //路径上的点权之和
int vi[600];              //访问标志
const int inf = 99999999;         
int main()
{
    int n, m, c1, c2;
    cin >> n >> m >> c1 >> c2;
    fill(G[0], G[0] + 600 * 600, inf);     //路径设为inf=---不可到达
    for (int i = 0; i < n; i++)
        scanf("%d",&weight[i]);
    for (int i = 0; i < m; i++)
    {
        int a, b, ti;
        scanf("%d%d%d", &a, &b, &ti);
        G[a][b] = ti; G[b][a] = ti;
    }
    fill(dis,dis+600,inf);         //设置初值
    dis[c1] = 0;
    w[c1] = weight[c1]; num[c1] = 1;
    for (int i = 0; i < n; i++)           //循环一遍找有没有没有访问过的点而且从起点到j最短
    {
        int u = -1; int minlen = inf;
        for (int j = 0; j < n; j++)
        {
            if (dis[j] < minlen&&vi[j]==0)    //没有访问过而且小于最短距离
            {
                u = j; minlen = dis[j];
            }
        }
        if (u == -1)break;
        vi[u] = 1;
        for (int k = 0; k < n; k++)
        {
            if (dis[u] + G[u][k] < dis[k]&&G[u][k]!=inf)
            {
                dis[k] = dis[u] + G[u][k];
                num[k] = num[u];
                w[k] = w[u] + weight[k];
            }
            else if (dis[u] + G[u][k]==dis[k])
            {
                num[k] = num[u]+num[k];
                if (w[k] < w[u] + weight[k])w[k] = w[u] + weight[k];
            }
        }
    }
    cout << num[c2] << " " << w[c2];
    return 0;
}

猜你喜欢

转载自blog.csdn.net/luoshiyong123/article/details/82194390
今日推荐