长途旅行(压缩问题)
来源:互联网 发布:雷蛇驱动有mac版吗 编辑:程序博客网 时间:2024/04/30 06:15
题目
【问题描述】
JY是一个爱旅游的探险家,也是一名强迫症患者。
现在JY想要在C国进行一次长途旅行,C国拥有n个城市(编号为0,1,2…,n - 1),城市之间有m条道路,可能某个城市到自己有一条道路,也有可能两个城市之间有多条道路,通过每条道路都要花费一些时间。JY从0号城市开始出发,目的地为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
【样例解释】
第1组:0 -> 1 -> 2 :11 第2组:显然偶数时间都是不可能的。
【数据范围】
30%的数据满足:T≤10000
另有30%的数据满足:2≤n≤5 1≤m≤100
100%的数据满足: 2≤n≤50 1≤m≤100 1≤z≤10000 1≤T≤10^18
1≤Case≤5
分析
看了网上很多题解,并不是很明白,然后下定决心自己搞懂之后,觉得写一个仍旧不是很明白的题解,重要的是自己思考。
作为一个图论问题,首先要自己想一下自己会什么,比较明显的是这不是欧拉回路或者说网络流,那么就只有SPFA了(什么逻辑啊!!)
T比较大,所以说我们要想办法压缩,利用一个dp的思想—重叠子问题,意思是说第j时刻到达i点可能很很多种到达方式,如果我们能不总是重复计算,只需要到达了一次就不再计算,就达到了大量化简的目的(开玩笑这种题目不知道浪费了多少)。
首先直接给出思路:找出一个比较小的环(一般来说是自环或者0~1的来回路径),我们可以在这个环上走很多次才开始继续走,为什么这样可以达到压缩的目的呢,一个是比较数字化的等下直接从方程看待,另一个就是因为之前说过了到达的方式有很多种,说不定这就是一种,而且可能性很大!。
设这个环的大小为mod,则T=t+k*mod,当k=0的时候,一定不影响结果,所以可以这么操作。
压缩后d[i][j]表示在j时刻到达i点已经走过了的最小时间,这里的值%mod一定为j,比如mod=5,d[i][2]=12,就表示第一次走到i时间是2+k*mod的时候是12(k=2),因此接下来17、22、27…都可以通过不停地走那个环来达到。
最后来看答案d[n-1][t%mod],如果它的答案是t,说明刚好可以走到,如果是t-k*mod,那么就走几个环,所以只要d[n-1][t%mod]<=t就可以达到
至于方程的转移,实际上就是最短路问题,用SPFA,化简之处如例子:用一个状态就表达了17、22、27…能化简得少么?
代码
注意:出于个人习惯,代码中所有的点的标号都被+1
#include<queue>#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long LL;const LL inf=1e18+5;const int maxn=55,maxm=105,maxw=10000*2+5;struct edge{ int to,next,w;}E[maxm<<1];int Case,mod;int n,m,np,first[maxn];LL t;LL d[maxn][maxw];void add(int u,int v,int w){ E[++np]=(edge){v,first[u],w}; first[u]=np;}void Init(){ scanf("%d%d",&n,&m); cin>>t; mod=1e9; np=0; memset(first,0,sizeof(first)); int u1,u2,w; for(int i=1;i<=m;i++) { scanf("%d%d%d",&u1,&u2,&w); u1++,u2++; if(u1==1||u2==1) { mod=min(mod,2*w); } add(u1,u2,w); add(u2,u1,w); }}struct data{ int i,k;};bool inq[maxn][maxw];void SPFA(){ queue<data>q; for(int i=0;i<=n;i++) for(int j=0;j<=mod;j++) d[i][j]=inf; q.push((data){1,0}); d[1][0]=0; while(!q.empty()) { data i=q.front();q.pop(); inq[i.i][i.k]=0; for(int p=first[i.i];p;p=E[p].next) { int j=E[p].to,nk=(i.k+E[p].w)%mod; if(d[j][nk]>d[i.i][i.k]+E[p].w) { d[j][nk]=d[i.i][i.k]+E[p].w; if(inq[j][nk])continue; inq[j][nk]=1; q.push((data){j,nk}); } } }}void solve(){ if(mod==1e9) { printf("Impossible\n"); return; } SPFA(); if(d[n][t%mod]<=t) printf("Possible\n"); else printf("Impossible\n");}int main(){ //freopen("in.txt","r",stdin); scanf("%d",&Case); while(Case--) { Init(); solve(); } return 0;}
收获
压缩问题可以从冲突上分析究竟获得了多少化简,同样的也可以通过冲突来得到压缩算法
- 长途旅行(压缩问题)
- 长途旅行
- 期待,下一次长途旅行
- 旅行商问题 (状态压缩DP)
- 三进制状态压缩DP(旅行商问题TSP)HDU3001
- HDU3768 Shopping(状态压缩DP+spfa)旅行商问题
- 旅行商问题(状态压缩的DP)
- 叉姐的魔法训练(第七课)---- 在沙漠中的长途旅行
- 模拟赛 长途旅行(时间限制:1s;空间限制:256M)
- 感受 印度 的长途Bus旅行!
- HDU 4640 Island and study-sister(状态压缩DP+路径压缩)经典 旅行商问题
- POJ 3311 旅行商问题 状态压缩
- 状态压缩动态规划 -- 旅行商问题
- 旅行商问题(状态压缩dp)
- 旅行商问题(状态压缩dp)
- 最短路+状态压缩dp(旅行商问题)hdu-4568-Hunter
- 《挑战程序设计竞赛》 P191 旅行商问题(货担郎) 状态压缩
- POJ 3311 旅行商问题 状态压缩 dp
- 动态规划之袋鼠过河问题
- shellter免杀技术实战
- PAT练习题003
- Lambda 使用与注意事项
- readelf的demo
- 长途旅行(压缩问题)
- Python 学习7
- 51nod 1594 Gcd and Phi
- 计算机网络疑点学习
- 带清除空能和匹配功能的自定义EditText
- RPGMaker MV 插件基础01:制作一个插件
- iOS学习笔记-121.多线程20——NSOperation图片下载合成示例
- oracle 12c PDB里建立的用户登录不上去,显示 IO 错误: Unknown host specified
- (poj 1020 Anniversary Cake)<DFS的巧妙剪枝>