uva 11367 - Full Tank?(dijkstra TLE)

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;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值