题目意思:输入数据第一行给出N,代表N个地点,C,C个车坏掉的地点,R,R条直通道路。 接下来给出C+1个字符串,其中第一个代表汽车修理总部,剩余C个代表车发生故障的地点。 接下来R行,给出R条直通道路,形式是 (地点1 关系 地点2),关系包含两者的互通 关系和距离。关系中仅有'>'代表这条路是从地点1到地点2的单向道路,关系中仅存在'<'代表这条路是从地点2到地点1的单向道路。 关系中既有'>'又有'<'代表这条路是双向道路,可以从地点1到地点2,也可以从地点2到地点1. 求解从汽车修理总部将所有坏掉的车运回来的最小花费。 与此题相似的题目有:POJ 1511题目 Invitation Cards(不过这个题目节点数目比较多,难度较这个题目大) 解题思路: 难点:将字符串对应与整形的节点编号,使用stl的map映射。同类型的题目还有杭电的2112题HDU Today.也是牵涉到要将字符串 表示的节点转化为整型编号。 小提示:题目中已指出,两个点之间可能存在多条道路,所以一定要考虑取最短的那一条路;很多人会想如果多辆车在同一地点坏掉, 可以同时将这些车拖回来,经过亲身实验证明,这样的做法提交后结果为Wrong Answer,说明每次只能拖一辆坏的车回去;一定要 注意这个题目的图是有向图。如果从汽车修理部到某个点运汽车,则去的路和回来的路不一定是相同的。mincost = 洗车修理部 到每个车坏的点的距离 + 每个车坏掉的点到汽车修理部的距离.在此提供两种解题方法。 方法1:构建两个图,一个图是题中给出的原图,第二个图为与题中给出图完全相反的图。 因为输入的时候第一个字符串是汽车修理总部,则按照代码,汽车修理总部的节点编号为1,则先在原图上求出节点1到其他节点的最短 路径。然后再在反向图中求1到其他点的最短路径。(相当于求了其他点到1的最短路径,仔细想想是不是这样)
#include<iostream> #include<cstdio> #include<queue> #include<vector> #include<cstring> #include<string> #include<stack> #include<map> #include<set> #define INF 0x3f3f3f3f #define MAXN 102 using namespace std; int Map[MAXN][MAXN][2]; ///Map[MAXN][MAXN][0]用来存放正向图,Map[MAXN][MAXN][1]用来存放反向图 int dis[MAXN][2],vis[MAXN]; ///dis[MAXN][0]用来存放正向图,节点1到各个点的最短路径。 ///dis[MAXN][1]用来存放反向图,求节点1到各个点的最短路径。相当于求各个点到1的最短路径。 ///vis是用来标记的数组。 int N,C,R; void InitMap() ///初始化地图 { for(int k = 0; k < 2; k++) { for(int i = 1; i <= N; i++) { Map[i][i][k] = 0; for(int j = i+1; j <= N; j++) Map[i][j][k] = Map[j][i][k] = INF; } } } void Dijkstra(int a) ///参数a代表求那个图的最短路径,0代表求原图,1代表求反图 { int mindis,u; for(int i = 1; i <= N; i++) { vis[i] = 0; dis[i][a] = Map[1][i][a]; } vis[1] = 1; for(int i = 1; i <= N; i++) { mindis = INF; u = 0; for(int j = 1; j <= N; j++) { if(vis[j]==0 && dis[j][a]<mindis) { u = j; mindis = dis[j][a]; } } if(u == 0) break; vis[u] = 1; for(int j = 1; j <= N; j++) { if(vis[j]==0) { if(dis[u][a]+Map[u][j][a]<dis[j][a]) { dis[j][a] = dis[u][a]+Map[u][j][a]; } } } } } int main() { int t = 0; while(~scanf("%d%d%d",&N,&C,&R)) ///N是location的个数,C是出故障的车的数目,R是直通道路条数 { if(N==0 && C==0 && R==0) break; ///程序结束条件 InitMap(); ///完成图的初始化工作 map<string,int>m; vector<int>v; char pos1[12],pos2[12],dist[50]; int num = 0; for(int i = 0; i <= C; i++) { scanf("%s",pos1); ///输入城市。 if(!m[pos1]) { m[pos1] = (++num); } v.push_back(m[pos1]); } int _go,_back,sub1,sub2,_dist; for(int i = 0; i < R; i++) { _go = _back = _dist = 0; scanf("%s%s%s",pos1,dist,pos2); if(!m[pos1]) m[pos1] = (++num); sub1 = m[pos1]; if(!m[pos2]) m[pos2] = (++num); sub2 = m[pos2]; for(int j = 0; j < strlen(dist); j++) { if(dist[j]=='>') _go = 1; if(dist[j]=='<') _back = 1; if(dist[j]>='0'&&dist[j]<='9') _dist = _dist*10 + (dist[j]-'0'); } if(_go) ///sub1到sub2有路 { if(_dist < Map[sub1][sub2][0]) { Map[sub1][sub2][0] = _dist; Map[sub2][sub1][1] = _dist; } } if(_back) ///sub2到sub1有路 { if(_dist < Map[sub2][sub1][0]) { Map[sub2][sub1][0] = _dist; Map[sub1][sub2][1] = _dist; } } } Dijkstra(0); Dijkstra(1); int ans = 0; for(int i = 0; i < v.size(); i++) { ans = ans + dis[v[i]][0] + dis[v[i]][1]; } printf("%d. %d\n",++t,ans); } return 0; } 方法2:直接采用Flody算法来计算任意两点间的最短路径。不过一开始害怕超时,放弃了,后来试了试,也是可以过滴。 #include<iostream> #include<cstdio> #include<queue> #include<vector> #include<cstring> #include<string> #include<stack> #include<map> #include<set> #define INF 0x3f3f3f3f #define MAXN 102 using namespace std; int Map[MAXN][MAXN]; int N,C,R; void InitMap() { for(int i = 1; i <= N; i++) { Map[i][i] = 0; for(int j = i+1; j <= N; j++) { Map[i][j] = Map[j][i] = INF; } } } void Flody() { for(int k = 1; k <= N; k++) { for(int i = 1; i <= N; i++) { for(int j = 1; j <= N; j++) { if(Map[i][k]+Map[k][j] < Map[i][j]) Map[i][j] = Map[i][k]+Map[k][j]; } } } } int main() { int t = 0; while(~scanf("%d%d%d",&N,&C,&R)) ///N是location的个数,C是出故障的车的数目,R是直通道路条数 { if(N==0 && C==0 && R==0) break; ///程序结束条件 InitMap(); ///完成图的初始化工作 map<string,int>m; vector<int>v; ///用容器保存汽车出故障的地点 char pos1[12],pos2[12],dist[50]; int num = 0; for(int i = 0; i <= C; i++) { scanf("%s",pos1); ///输入城市。 if(!m[pos1]) { m[pos1] = (++num); } v.push_back(m[pos1]); } int _go,_back,sub1,sub2,_dist; for(int i = 0; i < R; i++) { _go = _back = _dist = 0; scanf("%s%s%s",pos1,dist,pos2); if(!m[pos1]) m[pos1] = (++num); sub1 = m[pos1]; if(!m[pos2]) m[pos2] = (++num); sub2 = m[pos2]; for(int j = 0; j < strlen(dist); j++) { if(dist[j]=='>') _go = 1; if(dist[j]=='<') _back = 1; if(dist[j]>='0'&&dist[j]<='9') _dist = _dist*10 + (dist[j]-'0'); } if(_go) ///sub1到sub2有路 { if(_dist < Map[sub1][sub2]) { Map[sub1][sub2] = _dist; } } if(_back) ///sub2到sub1有路 { if(_dist < Map[sub2][sub1]) { Map[sub2][sub1] = _dist; } } } Flody(); int ans = 0; for(int i = 0; i < v.size(); i++) { ans = ans + Map[1][v[i]] + Map[v[i]][1]; } printf("%d. %d\n",++t,ans); } return 0; }