是时候表演真正的技术了
Time Limit 1000MS
Memory Limit 256MB
题目链接https://csustacm.fun/problem/1097
emmm,首先想到的就是暴力。。。直接每个点跑一遍最短路看看它们到哪个宝藏最近。即使经过优化之后也是n2log(n)的复杂的,直接T。
稍微好一点的就是将每个宝藏跑一遍最短路然后每个点取最小值。复杂度还是很高会T,不过当时LJ大佬就是用这种方法的,T了之后努力剪枝然后,就A了。。。神TM一般的剪枝。。。。
接下来就是一般的正解了,我们直接将所有宝藏的坐标压如队列就好了,这样我们只要跑一遍最短路用优化dj跑的话就是nlog(n),1e5的数据随便过
以下是AC代码:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mac=1e5+10;
const ll inf=1e16+7;
int vis[mac];
ll dis[mac];
struct node
{
ll to,cost;
};
struct node1
{
int id;
ll s;
bool friend operator <(node1 a,node1 b){
return a.s>b.s;
}
};
vector<node>g[mac];
int n;
void dj();
int main()
{
int m,k,x;
scanf ("%d%d%d",&n,&m,&k);
for (int i=1; i<=n; i++) dis[i]=inf;
for (int i=1; i<=k; i++){
scanf ("%d",&x);
dis[x]=0;
}
int u,v,w;
for (int i=1; i<=m; i++){
scanf ("%d%d%d",&u,&v,&w);
node s;
s.to=v; s.cost=w;
g[u].push_back(s);
s.to=u;
g[v].push_back(s);
}
int q;
dj();
scanf ("%d",&q);
while (q--){
scanf ("%d",&x);
printf ("%lld\n",dis[x]);
}
return 0;
}
void dj()
{
priority_queue<node1>q;
for (int i=1; i<=n; i++){
node1 w;
if (!dis[i]){
w.id=i; w.s=0;
q.push(w);
}
}
while (!q.empty()){
node1 rs=q.top();
q.pop();
int now=rs.id;
if (vis[now]) continue;
vis[now]=1;
for (int i=0; i<g[now].size(); i++){
if (dis[now]+g[now][i].cost<dis[g[now][i].to]){
dis[g[now][i].to]=dis[now]+g[now][i].cost;
node1 we;
we.id=g[now][i].to;
we.s=dis[g[now][i].to];
q.push(we);
}
}
}
}