1003 Emergency (25 分)

    xiaoxiao2024-11-02  77

    一、题目

    大意:n个城市以及他们之间的m条路构成了图,每个城市驻有大小不同的救援队,你所在的城市为c1,当c2发生险情时,你需要带领c1城市的救援队按最短路径赶往c2,所经过城市的救援队也会加入你们。输入:n(城市数),m(路数),c1(你所在城市),c2(需要救援的城市);每个城市驻扎救援队数目;m条路的起点、终点、长度。输出:最短路径的数目以及在这些路径中所能集合的救援队最大数目。

    二、分析

    在Dijkstra中,当一个顶点v加入到最短路径集合S中时,需要更新c1到其余未加入S顶点的距离,这时有三种情况(用Length[i]表示从c1到i的最短路径长度,用Graph[v][i]表示从v直接到j而不经过中间点的距离,RoadNum[i]表示从c1到i的最短路径数目,MaxRanks[i]表示在从c1到i的最短路径中能集合的最大救援队数目): ①、Length[i]<Length[v]+Graph[v][i],这种情况下最短路径还是Length[i],不需做任何改动。 ②、Length[i]=Length[v]+Graph[v][i],注意Length[i]此时还未更新,也就是说Length[i]表示的是在v还未加入S时,c1以S中某些点为中间点到i的距离,这条路径是不经过v的;而Length[v]+Graph[v][i]表示c1经过v到i的一条(或多条)路的长度,所以这两条(或多条)路是不会重合的。这个时候,从c1到i的最短路就是从c1不经过v到i的路(RoadNum[i])+经过v的路(RoadNum[v]);救援队数目选这些路里边最大的那个。 RoadNum[j]+=RoadNum[v]; MaxRanks[j]=(MaxRanks[v]+Weight[j])>MaxRanks[j]? (MaxRanks[v]+Weight[j]):MaxRanks[j]; ③、Length[i]>Length[v]+Graph[v][i],这时候最短路径就是Length[v]+Graph[v][i]了,需要更新Length[i]。从c1到i就是从c1到v到i。 Length[j]=Length[v]+Graph[v][j]; MaxRanks[j]=MaxRanks[v]+Weight[j]; RoadNum[j]=RoadNum[v];

    三、代码

    #include <iostream> #include <memory.h> using namespace std; #define Maxnum 505 #define Infinity 1e8 int Graph[Maxnum][Maxnum];//两点之间边长 int Length[Maxnum];//从c1到i的长度 int MaxRanks[Maxnum];//从c1到i的救援队最大数 int RoadNum[Maxnum];//从c1到i的最短路径数 int Weight[Maxnum];//开始时顶点i处救援队数 bool Final[Maxnum];//用于Dijkstra算法标记顶点已加入最短路径集合 void Dijkstra(int n) { for (int i = 0; i < n; ++i) { int min=Infinity; int v=-1; for (int j = 0; j < n; ++j) { if(!Final[j]&&Length[j]<min){ v=j;min=Length[j]; } } if(v==-1)break; else Final[v]=true; for (int j = 0; j < n; ++j) { if(!Final[j]&&(Length[j]==Length[v]+Graph[v][j])){ //在Dijkstra基础上增加的 RoadNum[j]+=RoadNum[v]; MaxRanks[j]=(MaxRanks[v]+Weight[j])>MaxRanks[j]? (MaxRanks[v]+Weight[j]):MaxRanks[j]; } else if(!Final[j]&&((Length[j]>Length[v]+Graph[v][j]))){ Length[j]=Length[v]+Graph[v][j]; MaxRanks[j]=MaxRanks[v]+Weight[j]; RoadNum[j]=RoadNum[v]; } } } } int main(){ fill(Graph[0],Graph[0]+Maxnum*Maxnum,Infinity); fill(Length,Length+Maxnum,Infinity); fill(MaxRanks,MaxRanks+Maxnum,0); fill(RoadNum,RoadNum+Maxnum,0); memset(Final, false, sizeof(Final)); int n,m,c1,c2; cin>>n>>m>>c1>>c2; for (int i = 0; i < n; ++i) cin>>Weight[i]; for (int i = 0; i < m; ++i) { int row,col,dist; cin>>row>>col>>dist; Graph[row][col]=Graph[col][row]=dist; } Length[c1]=0; MaxRanks[c1]=Weight[c1]; RoadNum[c1]=1;//c1到c1有一条路 Dijkstra(n); cout<<RoadNum[c2]<<" "<<MaxRanks[c2]; return 0; }

    二刷:用dijkstra+dfs做

    #include<iostream> #include<vector> using namespace std; const int maxn = 510; const int inf = 0x3fffffff; int graph[maxn][maxn], dis[maxn], weight[maxn], mark[maxn], n, m, start, end1, cnt = 0, maxW = 0; vector<vector<int>>pre; vector<int>temp; void dijkstra(int start) { dis[start] = 0; for (int i = 0; i < n; i++) { int pos = -1, min = inf; for (int j = 0; j < n; j++) { if (mark[j] == 0 && dis[j] < min) { min = dis[j]; pos = j; } } if (pos == -1)return; mark[pos] = 1; for (int j = 0; j < n; j++) { if (mark[j] == 0) { if (graph[pos][j] + dis[pos] < dis[j]) { pre[j].clear(); pre[j].push_back(pos); dis[j] = dis[pos] + graph[pos][j]; } else if (graph[pos][j] + dis[pos] == dis[j]) pre[j].push_back(pos); } } } } void dfs(int e) { if (e == start) { temp.push_back(e); cnt++; int sumW = 0; for (int i = 0; i < temp.size(); i++)sumW += weight[temp[i]]; maxW = (maxW > sumW) ? maxW : sumW; temp.pop_back(); return; } temp.push_back(e); for (int i = 0; i < pre[e].size(); i++)dfs(pre[e][i]); temp.pop_back(); } int main() { cin >> n >> m >> start >> end1; pre.resize(n); for (int i = 0; i < n; i++) { dis[i] = inf; mark[i] = 0; for (int j = 0; j < n; j++) graph[i][j] = inf; } for (int i = 0; i < n; i++)cin >> weight[i]; for (int i = 0; i < m; i++) { int x, y, l; cin >> x >> y >> l; graph[x][y] = graph[y][x] = l; } dijkstra(start); dfs(end1); cout << cnt << " " << maxW << endl; return 0; }
    最新回复(0)