标签:i++ blog 数据 str open ges codec pac 联通图
给一个图,n 个点 m 条双向边,每条边有其长度。n 个点中有 k 个是特殊点,问任意两个特殊点的最短路是多少。
第一行三个整数 n m k
第二行 k 个整数 ,为各个特殊点
接下来 m 行,每行三个整数 x y d,表示 x 到 y 有一条长度为 d 的边
一个整数
5 5 3 1 3 5 1 2 3 2 3 4 3 4 1 4 5 8 1 5 19
7
样例中,1-3 的最短路为 7,3-5 的最短路为 9,1-5 的最短路为 16,因此答案为最小值 7
分析
想象所有的特殊点都在中央,而我们要求的就是:
那么当那根被称为“最短路”的橡皮筋只捆在特殊点上时,其中的最短的一部分就是我们要求的。
那么当我们在找最优解的过程就像把这根橡皮筋从无关点上一个点一个点的向特殊点收缩。
这听起来有些玄幻。
非常套路地,我们需要求出每个点的最短路(也就是多源最短路),但同时还要记录对应的源点
这样当我们拎着一条边的时候,如果这条边两端的端点不同,这条边对应的橡皮筋的部分长度为 A点的最短路+边长+B点最短路。
这样我们可以在求最短路的过程中顺便求解。
代码
1 #include<cstdio> 2 #include<queue> 3 #include<iostream> 4 #define maxn_E 5050500 5 #define maxn_P 1010100 6 #define INF 2147483647 7 using namespace std; 8 typedef pair<int,int> node; 9 priority_queue<node,vector<node>,greater<node> > q; 10 11 struct edge{ 12 int from,v,len; 13 }e[maxn_E]; 14 15 int first[maxn_P],tot,ans = INF,n,m,k,a,b,c,dis[maxn_P],sou[maxn_P],spe[maxn_P]; 16 bool book[maxn_P]; 17 18 void insert(int u,int v,int len){ 19 tot++; 20 e[tot].from = first[u]; 21 e[tot].v = v; 22 e[tot].len = len; 23 first[u] = tot; 24 } 25 26 void dijkstra(){ 27 for(int i = 1;i <= n;i++) dis[i] = INF; 28 for(int i = 1;i <= k;i++){ 29 q.push(make_pair(0,spe[i])); 30 dis[spe[i]] = 0; 31 sou[spe[i]] = spe[i]; 32 } 33 34 while(!q.empty()){ 35 node tmp = q.top(); 36 q.pop(); 37 38 int p = tmp.second; 39 40 if(!book[p]){ 41 book[p] = true; 42 for(int i = first[p];i;i = e[i].from){ 43 if(dis[p] != INF && dis[e[i].v] != INF && sou[p] != sou[e[i].v]) 44 ans = min(ans,dis[p]+e[i].len+dis[e[i].v]); 45 if(dis[e[i].v] > dis[p]+e[i].len && !book[e[i].v]){ 46 if(sou[e[i].v] != sou[p]) 47 sou[e[i].v] = sou[p]; 48 dis[e[i].v] = dis[p]+e[i].len; 49 q.push(make_pair(dis[e[i].v],e[i].v)); 50 // if(sou[p] != sou[e[i].v]) 51 // ans = min(ans,dis[p]+e[i].len+dis[e[i].v]); 52 } 53 } 54 } 55 } 56 } 57 58 int main(){ 59 scanf("%d%d%d",&n,&m,&k); 60 61 for(int i = 1;i <= k;i++) scanf("%d",&spe[i]); 62 63 for(int i = 1;i <= m;i++){ 64 scanf("%d%d%d",&a,&b,&c); 65 insert(a,b,c); 66 insert(b,a,c); 67 } 68 69 dijkstra(); 70 71 // for(int i = 1;i <= n;i++){ 72 // printf("%d/%d ",dis[i],sou[i]); 73 // } 74 75 printf("%d",ans); 76 77 return 0; 78 }
标签:i++ blog 数据 str open ges codec pac 联通图
原文地址:http://www.cnblogs.com/Chorolop/p/7257260.html