标签:text 表示 信息 结构 题解 注意 names eof 其他
多组测试数据,输入的第一行含一个整数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。
每组测试数据一行输出,如果存在题目所述路径输出“Possible”,否则“Impossible”,不含引号。
1 3 3 25 0 2 7 0 1 6 1 2 5
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; }
标签:text 表示 信息 结构 题解 注意 names eof 其他
原文地址:http://www.cnblogs.com/renjianshige/p/7588125.html