BZOJ 2725 [Violet 6]故乡的梦 最短路

来源:互联网 发布:装甲少女 知乎 编辑:程序博客网 时间:2024/04/30 15:05
#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#define N 200005#define INF (1ll<<60)using namespace std;typedef long long LL;namespace Segment_Tree {    struct Node {        Node* ch[2];        int l,r;        LL v;        Node() {}        Node(int _l,int _r):l(_l),r(_r),v(INF) {            ch[0]=ch[1]=NULL;        }        void* operator new(size_t) {            static Node *mempool,*C;            if(mempool==C) mempool=(C=new Node[1<<20])+(1<<20);            return C++;        }    }*root;    void Init(Node*& o,int l,int r) {        o=new Node(l,r);        if(l==r) return ;        int mid=l+r>>1;        Init(o->ch[0],l,mid), Init(o->ch[1],mid+1,r);        return ;    }    void Change(Node* o,int l,int r,LL v) {        if(o->l==l && o->r==r) {            o->v=min(o->v,v);            return ;        }        int mid=o->l+o->r>>1;        if(r<=mid) Change(o->ch[0],l,r,v);        else if(l>mid) Change(o->ch[1],l,r,v);        else Change(o->ch[0],l,mid,v), Change(o->ch[1],mid+1,r,v);        return ;    }    LL Query(Node* o,int pos) {        if(o->l==o->r) return o->v;        int mid=o->l+o->r>>1,dir=pos<=mid?0:1;        return min(Query(o->ch[dir],pos),o->v);    }}#define ST Segment_Treestruct Data {    int ord;    LL val;    Data() {}    Data(int _ord,LL _val):ord(_ord),val(_val) {}    bool operator < (const Data& rhs) const {        return val>rhs.val;    }};struct Edge {    int from,to,nxt,val;    Edge() {}    Edge(int _from,int _to,int _nxt,int _val):        from(_from),to(_to),nxt(_nxt),val(_val) {}}e[N*2];int n,m,tot,S,T,Q,top,fir[N],fromS[N],fromT[N],seq[N],pos[N];LL distS[N],distT[N],ans[N];void Add_Edge(int u,int v,int c) {    e[++tot]=Edge(u,v,fir[u],c), fir[u]=tot;    e[++tot]=Edge(v,u,fir[v],c), fir[v]=tot;    return ;}void Dijkstra(int st,LL dist[]) {    static bool k[N];    priority_queue<Data> q;    for(int i=1;i<=n;++i) dist[i]=INF, k[i]=false;    dist[st]=0, q.push(Data(st,0));    while(!q.empty()) {        Data tmp=q.top(); q.pop();        int x=tmp.ord;        if(k[x]) continue;        k[x]=true;        for(int i=fir[x];~i;i=e[i].nxt) {            if(dist[e[i].to]<=dist[x]+e[i].val) continue;            dist[e[i].to]=dist[x]+e[i].val;            q.push(Data(e[i].to,dist[e[i].to]));        }    }    return ;}void Find_path() {    int x=S;    while(x!=T) {        seq[++top]=x;        pos[x]=top;        for(int i=fir[x];~i;i=e[i].nxt) {            if(distT[e[i].to]+e[i].val>distT[x]) continue;            x=e[i].to;            break;        }    }    seq[++top]=x, pos[x]=top;    return ;}void bfs(int ord,LL dist[],int from[]) {    int st=seq[ord];    queue<int> q;    q.push(st);    while(!q.empty()) {        int x=q.front(); q.pop();        for(int i=fir[x];~i;i=e[i].nxt)            if(!from[e[i].to] && dist[e[i].to]==dist[x]+e[i].val)                from[e[i].to]=ord, q.push(e[i].to);    }    return ;}void calc_from() {    for(int i=1;i<=top;++i) fromS[seq[i]]=fromT[seq[i]]=i;    for(int i=1;i<=top;++i) bfs(i,distS,fromS);    for(int i=top;i;--i) bfs(i,distT,fromT);    return ;}int main() {    memset(fir,-1,sizeof fir), tot=-1;    scanf("%d%d",&n,&m);    for(int i=1,x,y,z;i<=m;++i)        scanf("%d%d%d",&x,&y,&z), Add_Edge(x,y,z);    scanf("%d%d",&S,&T);    Dijkstra(S,distS), Dijkstra(T,distT);    Find_path(), calc_from();    ST::Init(ST::root,1,top-1);    for(int i=0;i<=tot;++i) {        int from=e[i].from,to=e[i].to;        if(pos[from] && pos[to] && abs(pos[from]-pos[to])==1) continue;        if(fromS[from] && fromT[to] && fromS[from]<fromT[to]) ST::Change(ST::root,fromS[from],fromT[to]-1,distS[from]+e[i].val+distT[to]);    }    for(int i=1;i<top;++i) ans[i]=ST::Query(ST::root,i);    for(scanf("%d",&Q);Q;--Q) {        int x,y;        scanf("%d%d",&x,&y);        if(pos[x]>pos[y]) swap(x,y);        LL tmp;        if(pos[x] && pos[y] && pos[x]+1==pos[y]) tmp=ans[pos[x]];        else tmp=distS[T];        printf(tmp==INF ? "Infinity\n" : "%lld\n",tmp);    }    return 0;}
原创粉丝点击