最短路的变形,因为要加上最大的点权,所以只能枚举以每一个点为起始点且为最大点权的最短路。
则对于每次询问有 Min = min(Min,dis[i][s] + dis[i][t] + val[i])。
然后此题需要好多细节上的优化。
比如,能用全局就用全局。
然后又重新搞了一遍SPFA。。。。竟然不会写了。。。。
以前写最短路一直在用bfs + priority_queue,不过竟然比spfa慢。。。
-------------------------updata------------------------------
其实bfs + priority_queue还是蛮可以的 . . . .一定是上次写挫了。。。。最后面附上bfs+priority_queue的代码。
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 1e18
#define Mod 6000007
using namespace std;
LL val[1010];
struct N
{
LL w;
int v,next;
}edge[40010];
int head[1010];
int Top;
void Link(int u,int v,LL w)
{
edge[Top].v = v;
edge[Top].w = w;
edge[Top].next = head[u];
head[u] = Top++;
}
LL dis[1010];
bool mark[1010];
queue<int> q;
void Cal(int s,int n)
{
memset(mark,false,sizeof(bool)*(n+2));
int f,t;
for(int i = 1;i <= n; ++i)
dis[i] = INF;
f = s;
dis[s] = 0;
q.push(f);
mark[s] = true;
while(q.empty() == false)
{
f = q.front();
q.pop();
mark[f] = false;
for(int p = head[f];p != -1; p = edge[p].next)
{
if(val[edge[p].v] > val[s])
continue;
if(dis[f] + edge[p].w < dis[edge[p].v])
{
dis[edge[p].v] = dis[f] + edge[p].w;
if(mark[edge[p].v] == false)
{
mark[edge[p].v] = true;
t = edge[p].v;
q.push(t);
}
}
}
}
}
int S[20010],T[20010];
LL Min[20010];
int main()
{
int n,m,i,j,u,v;
LL w;
while(scanf("%d %d",&n,&m) && (n||m))
{
memset(head,-1,sizeof(int)*(n+2));
Top = 0;
for(i = 1;i <= n; ++i)
{
scanf("%lld",&val[i]);
}
for(i = 1;i <= m; ++i)
{
scanf("%d %d %lld",&u,&v,&w);
Link(u,v,w);
Link(v,u,w);
}
scanf("%d",&m);
for(i = 0;i < m; ++i)
{
scanf("%d %d",&S[i],&T[i]);
Min[i] = INF;
}
for(i = 1;i <= n; ++i)
{
Cal(i,n);
for(w = 0;w < m; ++w)
{
Min[w] = min(Min[w],dis[S[w]] + dis[T[w]] + val[i]);
}
}
for(i = 0;i < m; ++i)
{
if(Min[i] == INF)
printf("-1\n");
else
printf("%lld\n",Min[i]);
}
printf("\n");
}
return 0;
}
bfs+priority_queue
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#pragma comment(linker, "/STACK:1024000000");
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 1e18
#define Mod 6000007
using namespace std;
LL val[1010];
struct N
{
LL w;
int v,next;
}edge[40010];
int head[1010];
int Top;
void Link(int u,int v,LL w)
{
edge[Top].v = v;
edge[Top].w = w;
edge[Top].next = head[u];
head[u] = Top++;
}
LL dis[1010];
bool mark[1010];
struct Q
{
int v;
LL cost;
bool operator < (const Q &a) const {
return a.cost < cost;
}
};
priority_queue<Q> q;
void Cal(int s,int n)
{
memset(mark,false,sizeof(bool)*(n+2));
Q f,t;
for(int i = 1;i <= n; ++i)
dis[i] = INF;
f.v = s;
f.cost = 0;
q.push(f);
while(q.empty() == false)
{
f = q.top();
q.pop();
if(mark[f.v])
continue;
mark[f.v] = true;
dis[f.v] = f.cost;
for(int p = head[f.v];p != -1; p = edge[p].next)
{
if(val[edge[p].v] > val[s])
continue;
t.v = edge[p].v;
t.cost = edge[p].w + f.cost;
if(dis[t.v] > t.cost)
{
dis[t.v] = t.cost;
q.push(t);
}
}
}
}
int S[20010],T[20010];
LL Min[20010];
int main()
{
int n,m,i,j,u,v;
LL w;
while(scanf("%d %d",&n,&m) && (n||m))
{
memset(head,-1,sizeof(int)*(n+2));
Top = 0;
for(i = 1;i <= n; ++i)
{
scanf("%lld",&val[i]);
}
for(i = 1;i <= m; ++i)
{
scanf("%d %d %lld",&u,&v,&w);
Link(u,v,w);
Link(v,u,w);
}
scanf("%d",&m);
for(i = 0;i < m; ++i)
{
scanf("%d %d",&S[i],&T[i]);
Min[i] = INF;
}
for(i = 1;i <= n; ++i)
{
Cal(i,n);
for(w = 0;w < m; ++w)
{
Min[w] = min(Min[w],dis[S[w]] + dis[T[w]] + val[i]);
}
}
for(i = 0;i < m; ++i)
{
if(Min[i] == INF)
printf("-1\n");
else
printf("%lld\n",Min[i]);
}
printf("\n");
}
return 0;
}