思路:最短路+SPFA / 最短路+floyd
分析:
1 题目要求的是有n个点,然后有c个破车,这个c个破车可能在同一城市里面,现在要把这些破车统一拉到中心点1.
2 这题的中心在1点,那么所求 ans = 1->所有破车的距离之和 + 所有破车->1的之和。所以这里涉及到1->所有破车的距离 和 所有破车->1的距离,那么我们可以使用SPFA和floyd。如果使用的是floyd那么最后的ans = dis[1][i]+dis[i][1];如果是SPFA就要先求一下1->所有破车的距离之和,然后在重新建图就是把边反向然后对1点SPFA ,在加上1->所有破车的和即可。
4 点的表示,利用map映射。
3 这一题给的n虽然才100,但是利用SPFA的时候要数组记得开1010,因为c最大为1000.这个地方杭电是WA,不给RE,所以我WA了40+。
代码:
/*floyd*/ #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<map> using namespace std; #define MAXN 110 #define INF 0xFFFFFFF int n , m , r , cnt; int value[MAXN][MAXN]; int num[1010]; char ch[1010][20]; map<string , int>mp; void init(){ for(int i = 1 ; i <= n ; i++){ for(int j = 1 ; j <= n ; j++) value[i][j] = INF; value[i][i] = 0; } } void input(){ int a , b , v; cnt = 0; char str1[MAXN] , str2[MAXN] , ch1 , ch2; mp.clear(); for(int i = 1 ; i <= m+1 ; i++){ scanf("%s" , ch[i]); a = mp[ch[i]]; if(!a) a = mp[ch[i]] = ++cnt; num[i] = a; } for(int i = 0 ; i < r ; i++){ scanf("%s" , str1); while((ch1 = getchar()) == ' '); scanf("-%d-%c %s" , &v , &ch2 , str2); a = mp[str1]; b = mp[str2]; if(!a) a = mp[str1] = ++cnt; if(!b) b = mp[str2] = ++cnt; if(ch1 == '<' && ch2 == '>'){ if(value[a][b] > v) value[a][b] = v; if(value[b][a] > v) value[b][a] = v; } else if(ch1 == '<' && ch2 == '-'){ if(value[b][a] > v) value[b][a] = v; } else{ if(value[a][b] > v) value[a][b] = v; } } } void floyd(){ for(int k = 1 ; k <= n ; k++){ for(int i = 1 ; i <= n ; i++){ for(int j = 1 ; j <= n ; j++){ if(value[i][j] > value[i][k] + value[k][j]) value[i][j] = value[i][k] + value[k][j]; } } } } int main(){ int ans , Case = 1; while(scanf("%d%d%d" , &n , &m , &r) && n+m+r){ init(); input(); floyd(); ans = 0; for(int i = 2 ; i <= m+1 ; i++) ans += value[1][num[i]] + value[num[i]][1]; printf("%d. %d\n" , Case++ , ans); } return 0; }
/*SPFA*/ #include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<queue> #include<map> using namespace std; #define MAXN 1010 #define INF 0xFFFFFFF int n , m , r , cnt; int value[MAXN][MAXN]; int tmpValue[MAXN][MAXN]; char ch[MAXN][20]; int dis[MAXN]; int vis[MAXN]; int num[MAXN]; queue<int>q; map<string , int>mp; void init(){ for(int i = 1 ; i <= n ; i++){ for(int j = 1 ; j <= n ; j++) value[i][j] = INF; value[i][i] = 0; } } void input(){ int a , b , v; cnt = 0; char str1[MAXN] , str2[MAXN] , ch1 , ch2; mp.clear(); for(int i = 1 ; i <= m+1 ; i++){ scanf("%s" , ch[i]); a = mp[ch[i]]; if(!a) a = mp[ch[i]] = ++cnt; num[i] = a; } for(int i = 0 ; i < r ; i++){ scanf("%s" , str1); while((ch1 = getchar()) == ' '); scanf("-%d-%c %s" , &v , &ch2 , str2); a = mp[str1]; b = mp[str2]; if(!a) a = mp[str1] = ++cnt; if(!b) b = mp[str2] = ++cnt; if(ch1 == '<' && ch2 == '>'){ if(value[a][b] > v) value[a][b] = v; if(value[b][a] > v) value[b][a] = v; } else if(ch1 == '<' && ch2 == '-'){ if(value[b][a] > v) value[b][a] = v; } else{ if(value[a][b] > v) value[a][b] = v; } } } /*重新建图*/ void rebuild(){ memcpy(tmpValue , value , sizeof(value)); init(); for(int i = 1 ; i <= cnt ; i++){ for(int j = 1 ; j <= cnt ; j++){ if(tmpValue[i][j]){ value[j][i] = tmpValue[i][j]; } } } } /*SPFA算法*/ void SPFA(){ memset(vis , 0 , sizeof(vis)); for(int i = 2 ; i <= cnt ; i++) dis[i] = INF; dis[1] = 0; vis[1] = 1; q.push(1); while(!q.empty()){ int x = q.front(); q.pop(); vis[x] = 0; for(int i = 1 ; i <= cnt ; i++){ if(value[x][i] && dis[i] > dis[x] + value[x][i]){ dis[i] = dis[x] + value[x][i]; if(!vis[i]){ vis[i] = 1; q.push(i); } } } } } int main(){ int ans , Case = 1; while(scanf("%d%d%d" , &n , &m , &r) && n+m+r){ init(); input(); SPFA();/*第一次SPFA*/ ans = 0; for(int i = 2 ; i <= m+1 ; i++) ans += dis[num[i]]; rebuild();/*图重建*/ SPFA();/*第二次SPFA*/ for(int i = 2 ; i <= m+1 ; i++) ans += dis[num[i]]; printf("%d. %d\n" , Case++ , ans); } return 0; }