B - TT 的旅行日记

浪尽此生 提交于 2020-04-07 09:53:53

https://vjudge.net/contest/365635#problem/B

建两层图,因为只能跑一条商业线,可以从正常点向虚拟点建一条单向边
For(i,1,m){
in(x);in(y);in(v);
push(x,y,v);
push(y,x,v);
push(x+n,y+n,v);
push(y+n,x+n,v);
}
in(k);
For(i,1,k){
in(x);in(y);in(v);
push(x,y+n,v);
push(y,x+n,v);
}
看这个建图过程就应该能明白。
if(d[t+n]<d[t]) 意味着走商业线更短
否则经济线更短
对于那个商业线的点,就是从大于n的点到小于等于n的点过度的时候,也就是从虚拟图跑到实图的那一条边

 

#include <iostream>
#include <cstdio>
#include <queue>
#include <algorithm>
#include <stack>
#include <cstring>
#define inf 2147483647
#define N 1000010
#define p(a) putchar(a)
#define For(i,a,b) for(int i=a;i<=b;++i)

using namespace std;
int n,s,t,m,x,y,v,k,temp,cnt;
int d[N],f[N];
bool vis[N],flag;
deque<int>q;
stack<int>st;
struct node{
    int n;
    int v;
    node *next;
}*e[50000];

void in(int &x){
    int y=1;char c=getchar();x=0;
    while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();}
    while(c<='9'&&c>='0'){ x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    x*=y;
}
void o(int x){
    if(x<0){p('-');x=-x;}
    if(x>9)o(x/10);
    p(x%10+'0');
}

void push(int x,int y,int v){
    node *p;
    p=new node();
    p->v=v;
    p->n=y;
    if(e[x]==0)
        e[x]=p;
    else{
        p->next=e[x]->next;
        e[x]->next=p;
    }
}

void clear(){
    memset(e,0,sizeof(e));
    flag=0;
}

void spfa(){
    For(i,0,2*n) d[i]=inf;
    d[s]=0;f[s]=s;
    q.push_back(s);
    while(!q.empty()){
        x=q.front();q.pop_front();
        vis[x]=1;
        for(node *i=e[x];i;i=i->next){
            if(d[i->n]>d[x]+i->v){
                d[i->n]=d[x]+i->v;
                f[i->n]=x;
                if(!vis[i->n]){
                    if(!q.empty()&&d[i->n]<=d[q.front()]) q.push_front(i->n);
                    else q.push_back(i->n);
                }
            }
        }
        vis[x]=0;
    }
}

void print(){
    if(d[t]<d[t+n]){
        temp=t;
        while(temp!=f[temp]){
            st.push(temp);
            temp=f[temp];
        }
        st.push(s);
        while(!st.empty()){
            o(st.top());
            if(st.size()!=1) p(' ');
            else p('\n');
            st.pop();
        }
        puts("Ticket Not Used");
        o(d[t]);p('\n');
    }
    else{
        temp=t+n;
        while(temp!=f[temp]){
            if(temp>n) st.push(temp-n);
            else{
                st.push(temp);
                if(!flag) flag=1,k=temp;
            }
            temp=f[temp];
        }
        if(!flag) k=s;
        st.push(s);
        while(!st.empty()){
            o(st.top());
            if(st.size()!=1) p(' ');
            else p('\n');
            st.pop();
        }
        o(k);p('\n');
        o(d[t+n]);p('\n');
    }  
}

signed main(){
    while(cin>>n>>s>>t){
        if(cnt++) p('\n');
        in(m);
        clear();
        For(i,1,m){
            in(x);in(y);in(v);
            push(x,y,v);
            push(y,x,v);
            push(x+n,y+n,v);
            push(y+n,x+n,v);
        }
        in(k);
        For(i,1,k){
            in(x);in(y);in(v);
            push(x,y+n,v);
            push(y,x+n,v);
        }
        spfa();
        print();
    }
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!