51nod 1326

原题链接
road(0,n-1)=road(0, n-1的邻接点x)+edge(x,n-1)*2*k 构成!

选取mod,mod=min( edge(x, n-1) )。
SPFA跑一遍,求出G[u][d],
G[u][d]表示从0出发到达u的路径长度%mod=d的最短路径。
跑完之后,
枚举n-1的邻接点,再枚举d,看能否构造出T。

#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define debug puts("Infinity is awesome!")
#define mm(a, b) memset(a, b, sizeof(a))
#define LL long long
using namespace std;
const LL Inf=0x3f3f3f3f3f3f3f3f;
const int maxn=55;
const int maxe=105;
const int maxmod=2e4;
int n, m;
LL dist;
struct Edge{
    int to, dist, next;
};
Edge edges[maxe];
int head[maxn], ecnt;
LL mod;
void Init(){
    memset(head, -1, sizeof head);
    ecnt=0;
}
void AddEdge(int u,int v,int d){
    edges[ecnt]=Edge{v, d, head[u]};
    head[u]=ecnt++;
}
struct Node{
    int p;
    LL dist;
};
LL G[maxn][maxmod];
void Pre(){
    for(int i=0;i<n;i++)
        for(int j=0;j<mod;j++)
        G[i][j]=Inf;
    queue<Node> Q;
    Q.push(Node{0, 0LL});
    while(!Q.empty()){
        Node x=Q.front(); Q.pop();
        int u=x.p, d=x.dist;
        if(d>G[u][d%mod]) continue;
        G[u][d%mod]=d;
        for(int i=head[u];i!=-1;i=edges[i].next){
            int v=edges[i].to;
            int d2=edges[i].dist;
            LL newd=d+d2;
            if(G[v][newd%mod]>G[u][d%mod]+d2){
                G[v][newd%mod]=G[u][d%mod]+d2;
                Q.push(Node{v, newd});
            }
        }
    }
}
int main(){
    int T;
    int cas=0;
    int u, v, d;

    //printf("%lld\n", Inf);
    scanf("%d", &T);
    while(T--){
        scanf("%d%d%lld", &n, &m, &dist);
        mod=2*1e4;
        Init();
        for(int i=0;i<m;i++){
            scanf("%d%d%d", &u, &v, &d);
            AddEdge(u, v, d);
            AddEdge(v, u, d);
            if(u==n-1||v==n-1) mod=min(mod, 2LL*d);
        }
        //printf("mod=%lld\n", mod);
        Pre();
        int flag=0;
        for(int i=head[n-1];i!=-1&&!flag;i=edges[i].next){
            int v=edges[i].to;
            int d=edges[i].dist;
            for(int j=0;j<mod;j++){
                //printf("v=%d j=%d d=%d cost=%lld\n", v, j, d, G[v][j]);
                if(G[v][j]<Inf&&(dist-G[v][j])%(2LL*d)==d){
                    //printf("%lld\n", G[v][j]);
                        flag=1;
                        break;
                }
            }
        }
        puts(flag?"Possible":"Impossible");
    }


    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值