潍坊一中模拟赛10.25 长途旅行

【题目描述】

JY是一个爱旅游的探险家,也是一名强迫症患者。现在JY想要在C国进行一次长途旅行,C国拥有n个城市(编号为0,1,2...,n - 1),城市之间有m条道路,可能某个城市到自己有一条道路,也有可能两个城市之间有多条道路,通过每条道路都要花费一些时间。JY0号城市开始出发,目的地为n – 1号城市。由于JY想要好好参观一下C国,所以JY想要旅行恰好T小时。为了让自己的旅行更有意思,JY决定不在任何一个时刻停留(走一条到城市自己的路并不算停留)JY想知道是否能够花恰好T小时到达n – 1号城市(每个城市可经过多次)。现在这个问题交给了你。

若可以恰好到达输出Possible”否则输出“Impossible”。(不含引号)

【输入格式】

第一行一个正整数Case,表示数据组数。

每组数据第一行3个整数,分别为n, m, T

接下来m行,每行3个整数x, y, z,代表城市x和城市y之间有一条耗时为z的双向边。

【输出格式】

对于每组数据输出”Possible”或者”Impossible”.

【样例输入】

2

3 3 11

0 2 7

0 1 6

1 2 5

2 1 10000

1 0 1

【样例输出】

Possible

Impossible

【样例解释】

第一组:0 -> 1 -> 2 :11

第二组:显然偶数时间都是不可能的。

【数据范围】

30%:  T <= 10000

另有30%: n <= 5 , m <= 10.

100%: 2 <= n <= 50 , 1 <= m <= 100 , 1 <= z <= 10000 , 1 <= T <= 10^18 , Case <= 5.

一张有重边和自环的无向图,一个人从0点出发,走到n-1处停止,一个城市可以反复走多次,每走一条边花费一定时间,是否能正好花费时间T

一看到能否,就知道是一种判定问题,主要矛盾在于,如果这么跑的话,会出现一个城市反复跑很多次,才能累加到T的情况,而累加到T,T<=10^18,时间上不允许,所以要压缩,而压缩最好的办法就是取余,在图论里减少走的次数的最好办法就是最短路,要把两者结合起来,发现从0点出来的一条边来回走可以形成一个2w的自环,于是用2w进行压缩,记录到每个点的距离,在mod2w的情况下的最小值,这样比这个值大的都可以看成是走过几次环之后的结果,这样就可以舍掉不要了,最后看dist[n-1][n%2w],如果结果不大于T,都可以用上几个2w填补,如果超了或者干脆到不了,就不行

既然是取余,肯定要选择最小的出边,这样状态也更少,时间上也优

 

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#define inf 987654321
#define ll long long
using namespace std;
char ch;
ll t,n,m,md;
struct edge{
    int v;
    int w;
};
struct dat{
    int d;
    int u;
};
vector<edge> g[55];
bool vis[55][10005];
ll dist[55][10005];
inline int read(){
    int x = 0,f = 1;
    char ch = getchar();
    while(ch<'0' || ch>'9'){
        if(ch=='-')f=-1;
        ch = getchar();
    }
    while(ch>='0'&&ch<='9'){
        x = x*10+ch-48;
        ch = getchar();
    }
    return x*f;
}
inline ll Read(){
    ll x = 0,f = 1;
    char ch = getchar();
    while(ch<'0' || ch>'9'){
        if(ch=='-')f=-1;
        ch = getchar();
    }
    while(ch>='0'&&ch<='9'){
        x = x*10+ch-48;
        ch = getchar();
    }
    return x*f;
}
void spfa(){
    memset(dist,63,sizeof(dist));
    memset(vis,false,sizeof(vis));
    dist[0][0] = 0;
    dat tmp;
    tmp.u = tmp.d = 0;
    queue<dat> q;
    q.push(tmp);
    while(!q.empty()){
        tmp = q.front();
        q.pop();
        int u = tmp.u,d = tmp.d,dd,to;
        vis[u][d] = false;
        for(int j = 0;j < g[u].size();j++){
            to = g[u][j].v;
            dd = g[u][j].w + dist[u][d];
            int nmod = dd%md;
            if(dist[to][nmod] > dd){
                dist[to][nmod] = dd;
                if(!vis[to][nmod]){
                    vis[to][nmod] = true;
                    tmp.d = nmod;
                    tmp.u = to;
                    q.push(tmp);
                }
            }
        }
        
    }
}
int main(){
    freopen("travel.in","r",stdin);
    freopen("travel.out","w",stdout);
    int T = read();
    edge tmp;
    while(T--){
        n = read();
        m = read();
        t = Read();
        md = inf;
        for(int i = 1;i <= m;i++){
            int u=read(),v=read(),w=read();
            tmp.v = v;
            tmp.w = w;
            g[u].push_back(tmp);
            tmp.v = u;
            g[v].push_back(tmp);
            if(md > w && (!u||!v)) md = w;
        }
        md*=2;
        spfa();
        if(dist[n-1][t%md] <= t) cout<<"Possible"<<endl;
        else cout<<"Impossible"<<endl;
        for(int i = 0;i <= n;i++) g[i].clear();
        
    }
    return 0;
}
原文地址:https://www.cnblogs.com/hyfer/p/5811887.html