Description
Loongint非常喜欢Dota这款游戏~但是他总是被Dota复杂的地图困扰,有时候甚至会因为地图太复杂而失去了自己Gank和Farm的节奏。所以他需要你的帮忙。
地图上一共有n个关键位置,每个关键位置有一个关键值Vi, 关键位置之间有m条双向的通路,每条通路有其通行值Ci,我们定义两关键位置之间的距离为其间的通路的通行值和加上路径上关键值最大的关键位置(包括起点终点)的关键值(样例如图)。
Loongint现在有Q个询问,对于每个询问,你需要告诉他a关键位置和b关键位置间的最短距离。
Input
第1行为三个数 n,m,q,
第2行到第n+1行表示关键位置的关键值Vi,
第n+2到第n+m+1行表示通路的起始位置和通行值,
第n+m+2到第n+m+q+1行表示q个询问,每个询问给出a,b。
Output
输出q行,每行对应一个询问的最短距离。
Sample Input
5 7 2
2
5
3
3
4
1 2 3
1 3 2
2 5 3
5 3 1
5 4 1
2 4 3
3 4 4
1 4
2 3
Sample Output
8
9
Hint
N≤250,M≤10,000
Q≤10,000;Vi,Ci≤100,000
【分析】
首先看到N只有250,显然O(N^3)的算法是可行的。于是便想到了floyd,又联想到floyd是基于DP原则,那么这道题应该就是这个方向了。由floyd算法知,最外层循环若走到k这个值,那么邻接矩阵中的数的意义就是以{1,2,...,k}为中介的最短路。于是,我们把顶点按权值从小到大排序,以此对顶点重编号。然后按照这个编号的顺序,在最外层循环。可知第 k(u,v <= k) 次外层迭代后,d[u][v] + w[k] 就是以 k 为最大权值顶点的最小花费。
【代码】
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int N,M,Q;
int v[255],t[255],Map[255][255],g[255][255],rank[255];
void _in(int &x)
{
char t=getchar();
while(t<'0'||'9'<t) t=getchar();
for(x=t-'0',t=getchar();'0'<=t&&t<='9';x=x*10+t-'0',t=getchar());
}
void _out(int x,int j=1)
{
char t[100];
if(!x) putchar('0');
for(;x;x/=10,j++) t[j]=x%10+'0';
for(j--;j;j--) putchar(t[j]);
putchar('\n');
}
void _init()
{
int x,y,z;
_in(N);_in(M);_in(Q);
for(int i=1;i<=N;i++)
{
for(int j=1;j<=N;j++)
Map[i][j]=g[i][j]=999999999;
Map[i][i]=g[i][i]=0;
rank[i]=i;
}
for(int i=1;i<=N;i++)
_in(v[i]);
for(int i=1;i<=M;i++)
{
_in(x);_in(y);_in(z);
if(Map[x][y]>z)
{
Map[x][y]=z;
Map[y][x]=z;
}
}
}
void _qst_t(int l,int r)
{
int i=l,j=r,mt=t[(i+j)>>1];
while(i<=j)
{
while(t[i]<mt) i++;
while(t[j]>mt) j--;
if(i<=j)
{
swap(t[i],t[j]);
swap(rank[i],rank[j]);
i++;j--;
}
}
if(l<j) _qst_t(l,j);
if(i<r) _qst_t(i,r);
}
void _solve()
{
memcpy(t,v,sizeof(v));
_qst_t(1,N);
for(int o=1;o<=N;o++)
{
int k=rank[o];
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
if(Map[i][j]>=Map[i][k]+Map[k][j])
{
Map[i][j]=Map[i][k]+Map[k][j];
g[i][j]=min(g[i][j],Map[i][j]+max(v[k],max(v[i],v[j])));
}
}
int x,y;
for(int i=1;i<=Q;i++)
{
_in(x);_in(y);
_out(g[x][y]);
}
}
int main()
{
_init();
_solve();
return 0;
}