TLE 啊 TLE,我的想法和讨论版里的是一样的,为什么就是一直TLE呢。是每次查询都重做一遍dijkstra导致的吗?怎么还有人也那样却ac了呢。求大神解释啊。
代码啊,恶心的代码啊
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
//#include <map>
using namespace std;
const int maxn = 1000 + 5;
const int maxN = 100000 + 5;
const int INF = 1000000000;
struct Edge{
int from,to,dist;
bool operator <(const Edge& rhs) const{
if(from < rhs.from || from == rhs.from && to < rhs.to ||
from == rhs.from && to == rhs.to && dist < rhs.dist)
return true;
return false;
}
};
struct Node{
int px,d;
};
struct Mark{
int n,c;
}mark[maxN];//记录某个编号对应的状态
struct Heapnode{//优先队列的结点
int d,u;
bool operator < (const Heapnode& rhs) const{
return d > rhs.d;
}
};
struct Dijkstra{
int n,m;//原始点数和边数
vector<Edge> edges;//边列表
vector<int> G[maxN];//每个节点出发的边编号(从0开始)
bool done[maxN];//是否已永久编号
int d[maxN];//s到各个点的距离
vector<Node> match[maxn];//初始图中每个点相邻的那条边
int price[maxn];
int id[maxn][105];//某个状态对应的编号
int Count;
// map<Edge,int> M;
void init(int n){
this -> n = n;
for(int i = 0;i < maxN;i++) G[i].clear();//清空邻接表
edges.clear();//清空边表
//M.clear();
Count = 0;
for(int i = 0;i < maxn;i++)
for(int j = 0;j < 105;j++){
id[i][j] = -1;
}
}
void AddEdge(int from,int to,int dist){
//printf("1. %d-%d %d\n",from,to,dist);
//如果是无向图,每条无向边需调用两次AddEdge
/*if(M.count((Edge){from,to,dist}) != 0)
return;*/
//printf("2. %d-%d %d\n",from,to,dist);
edges.push_back((Edge){from,to,dist});
//M[(Edge){from,to,dist}] = 1;
m = edges.size();
G[from].push_back(m-1);//(m-1)因为边从0开始编号
}
int ID(int n,int c){
int x = id[n][c];
if(x == -1){
x = Count++;
id[n][c] = x;
mark[x].n = n;
mark[x].c = c;
}
return x;
}
void dijkstra(int s,int c){//求s到所有点的距离
priority_queue<Heapnode> Q;
for(int i = 0;i < maxN;i++) d[i] = INF;
d[s] = 0;
memset(done,0,sizeof(done));
Q.push((Heapnode){0,s});
while(!Q.empty()){
Heapnode x = Q.top();Q.pop();
int u = x.u;//u是这个节点的编号
if(done[u]) continue;
done[u] = true;
int minp = INF;//记录在这个点最小的c
int temn = mark[u].n;//当前节点的原图中位置
int temc = mark[u].c;//当前节点的c值
//走向其他点的边
for(int i = 0;i < match[temn].size();i++){
int temp = match[temn][i].px;//相邻点在原图中的位置
int temd = match[temn][i].d;//相邻边的距离
minp = min(minp,temd);
if(temc >= temd){
AddEdge(u,ID(temp,temc-temd),0);
//printf("%d-%d %d-%d\n",temn,temc,temp,temc-temd);
}
}
//加油的边
for(int i = max(1,minp-temc);i <= c-temc;i++){
AddEdge(u,ID(temn,temc+i),price[temn]*i);
}
for(int i = 0;i < G[u].size();i++){
Edge& e = edges[G[u][i]];
if(d[e.to] > d[u] + e.dist){
d[e.to] = d[u] + e.dist;
Q.push((Heapnode){d[e.to],e.to});
}
}
}
}
};
Dijkstra solver;
int main(){
int n,m,u,v,d;
while(scanf("%d%d",&n,&m) != EOF){
for(int i = 0;i < n;i++) solver.match[i].clear();
for(int i = 0;i < n;i++)
scanf("%d",&solver.price[i]);
while(m--){
scanf("%d%d%d",&u,&v,&d);
solver.match[u].push_back((Node){v,d});
solver.match[v].push_back((Node){u,d});
}
int q,c,s,t;
scanf("%d",&q);
while(q--){
scanf("%d%d%d",&c,&s,&t);
if(t < s) swap(s,t);
solver.init(n);
solver.dijkstra(solver.ID(s,0),c);
int ans = INF;
for(int i = 0;i <= c;i++){
ans = min(ans,solver.d[solver.ID(t,i)]);
}
//for(int i = 0;i < solver.Count;i++)
//printf("%d ",solver.d[i]);
if(ans == INF)
printf("impossible\n");
else
printf("%d\n",ans);
}
}
return 0;
}