51nod 1326 遥远的旅途

一个国家有N个城市,这些城市被标为0,1,2,...N-1。这些城市间连有M条道路,每条道路连接两个不同的城市,且道路都是双向的。一个小鹿喜欢在城市间沿着道路自由的穿梭,初始时小鹿在城市0处,它最终的目的地是城市N-1处。小鹿每在一个城市,它会选择一条道路,并沿着这条路一直走到另一个城市,然后再重复上述过程。每条道路会花费小鹿不同的时间走完,在城市中小鹿不花时间逗留。路程中,小鹿可以经过一条路多次也可以经过一个城市多次。给定城市间道路的信息,问小鹿是否有一种走法,从城市0出发到达城市N-1时,恰好一共花费T个单位的时间。如果存在输出“Possible”,否则输出“Impossible”。
注意,小鹿在整个过程中可以多次经过城市N-1,只要最终小鹿停在城市N-1即可。
 
例如样例中小鹿的行程可以是0->1->2->0->2.
Input
多组测试数据,输入的第一行含一个整数caseT,表示测试数据个数,1<=caseT<=3.
之后有caseT组相同结构的测试数据,每组测试数据构成如下:
第一行三个整数,N,M,T,且2<=N<=50,1<=M<=50,1<=T<=1,000,000,000,000,000,000(即
10^18).
之后M行,每行三个整数Ai,Bi,Di,表示城市Ai与Bi间有一条双向道路,且小鹿穿越这条路要花费Di的时间。其中,0<=Ai,Bi<N,1<=Di<=10000。
Output
每组测试数据一行输出,如果存在题目所述路径输出“Possible”,否则“Impossible”,不含引号。
Input示例
1
3 3 25
0 2 7
0 1 6
1 2 5
Output示例
Possible

题解:
  这个题目暴力dp,一定连空间都开不下,但这个已经是凑数模型的唯一状态,没有什么其他办法,所以,一定要想着题目中的其他限制或者说性质。
  因为这个是一个图论模型,所以转移就十分有限制,只能走边权,所以我们可以发现要凑出这个数,就一定是先到n号点,然后通过走一条边2*k遍来达到目的,所以我们可以列出式子,(t-dis(1~n))%2*k==0(k为和n号点相连的某条边的边权))
转化成t%(2*k)==dis(1~n)%(2*k)。用这个式子,我们就只要看是否存在一条到n的路径,使得路径的边权和%2*k等于一个定值t%(2*k)。
  因为这个题目和模数有关,所以我们要把取摸的结果写入状态,dp[i][j]表示处于i节点,从一号点到i号点的花费和%(2*k)(选择的边权)等与k的最小花费,那么转移就是dp[to][(j+quan)%mod]=min(dp[now][j]+quan).
  可以说是有限制的凑数问题吧,因为这个题目是一个图,有后效性,所以spfa。

代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <iostream>
#include <queue>
#define MAXN 200
#define MAXN2 20100
#define ll long long
using namespace std;
ll dis[MAXN][MAXN2];
bool have[MAXN][MAXN2];
struct edge{
    int first;
    int next;
    int to;
    int quan;
}a[MAXN*2];
struct node{
    int now,ti;
};
queue<node> q;
int n,m,num=0;ll t,mod;

void addedge(int from,int to,int quan){
    a[++num].to=to;
    a[num].quan=quan;
    a[num].next=a[from].first;
    a[from].first=num;
}

void spfa(){
    memset(dis,127,sizeof(dis));
    memset(have,0,sizeof(have));
    while(!q.empty()) q.pop();
    have[1][0]=1,dis[1][0]=0;
    q.push((node){1,0});
    while(!q.empty()){
        node hh=q.front();q.pop();
        int now=hh.now,t=hh.ti;
        have[now][t]=0;
        for(int i=a[now].first;i;i=a[i].next){
            int to=a[i].to,quan=a[i].quan,tt=(t+quan)%mod;
            if(dis[to][tt]>dis[now][t]+quan){
                dis[to][tt]=dis[now][t]+quan;
                if(!have[to][tt]){
                    have[to][tt]=1;
                    q.push((node){to,tt});
                }
            }
        }
    }
}

void work(){
    scanf("%d%d%lld",&n,&m,&t);
    memset(a,0,sizeof(a));int flag=0;num=0;
    for(int i=1;i<=m;i++){
        int x,y,z;scanf("%d%d%d",&x,&y,&z);x++,y++;
        addedge(x,y,z),addedge(y,x,z);
    }
    for(int i=a[n].first;i;i=a[i].next){
        int quan=a[i].quan;
        mod=quan*2;
        spfa();
        if(dis[n][t%mod]<=t){
            printf("Possible\n");flag=1;
            break;
        }
    }
    if(!flag){
        printf("Impossible\n");
    }
}

int main()
{
    int t;cin>>t;
    while(t--){
        work();
    }
    return 0;
}

 

posted @ 2017-09-24 18:57  人间失格—太宰治  阅读(398)  评论(0编辑  收藏  举报