NOIP模拟赛 长途旅行
2014年11月3日3,0274
「题目描述」
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
「样例解释」
第一组: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.
时间非常大,存在一个城市要经过很多次才能累加成T的情况,直接跑会超时。
如果存在一条连接0点的边长度为d(不存在的话直接Impossible),如果从0到n-1路径长度为D,并且D+2*k*d = T,则possible
这样原题就化为最短路问题了,dis[i][j] 代表到达i号点,时间为 j + p * 2d,最小的 j+p*2d。最后判断dis[n -1][T % 2d] 是否小于等于T即可,取d为最小的d更优一些
我的代码,不知道在哪里提交,并不保证对
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
const int INF = 1e18 + 5;
ll dis[55][200005],T;
bool vis[55][200005];
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;
}
struct node1
{
int to,Next;
ll w;
}edge[205];
int n;
int tot,head[55];
ll mod;
void init()
{
tot = 0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,ll w)
{
edge[tot].to = v;
edge[tot].w = w;
edge[tot].Next = head[u];
head[u] = tot++;
}
struct node2
{
int x,y;
node2(){}
node2(int _x,int _y)
{
x = _x;y = _y;
}
};
void spfa()
{
for(int i = 0; i < n; i++) {
for(int j = 0; j < mod; j++) {
dis[i][j] = INF;
}
}
memset(vis,0,sizeof(vis));
dis[0][0] = 0;
struct node2 temp;
temp.x = temp.y = 0;
queue<node2> q;
q.push(temp);
while(!q.empty()) {
temp = q.front();
q.pop();
int x = temp.x,y = temp.y;
vis[x][y] = false;
for(int i = head[x]; i != -1; i = edge[i].Next) {
int to = edge[i].to;
ll d = edge[i].w + dis[x][y];
int nmod = d % mod;
if(dis[to][nmod] > d) {
dis[to][nmod] = d;
if(!vis[to][nmod]) {
vis[to][nmod] = true;
q.push(node2(to,nmod));
}
}
}
}
}
int main(void)
{
int T,m,u,v;
ll t,w;
scanf("%d",&T);
while(T--) {
init();
mod = 10000000;
scanf("%d %d %lld",&n,&m,&t);
while(m--) {
scanf("%d %d %lld",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
if(mod > w && (u == 0 || v == 0)) mod = w;
}
if(mod == 10000000) {
printf("Impossible\n");
continue;
}
mod *= 2;
spfa();
if(dis[n - 1][t % mod] <= t) printf("Possible\n");
else printf("Impossible\n");
}
return 0;
}
其它博客的一个代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#define pa pair<int,int>
#define inf 1000000000
#define ll long long
using namespace std;
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-'0';ch=getchar();}
return x*f;
}
ll T;
int n,m,cas,cnt,last[55],mod;
int q1[10000005],q2[10000005];
ll dis[55][20005];
struct data{int to,next,v;}e[205];
void insert(int u,int v,int w)
{
e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w;
e[++cnt].to=u;e[cnt].next=last[v];last[v]=cnt;e[cnt].v=w;
if(u==1||v==1)mod=2*w;
}
bool spfa()
{
memset(dis,127/3,sizeof(dis));
int head=0,tail=1;
dis[1][0]=0;
q1[0]=1;q2[0]=0;
while(head!=tail)
{
int now=q1[head],t=q2[head];head++;
for(int i=last[now];i;i=e[i].next)
{
int to=(e[i].v+t)%mod;
if(dis[e[i].to][to]>dis[now][t]+e[i].v)
{
dis[e[i].to][to]=e[i].v+dis[now][t];
q1[tail]=e[i].to;
q2[tail]=to;
tail++;
}
}
}
if(dis[n][T%mod]<=T)return 1;
return 0;
}
int main()
{
//freopen("travel.in","r",stdin);
//freopen("travel.out","w",stdout);
cas=read();
while(cas--)
{
mod=-1;
memset(last,0,sizeof(last));
cnt=0;
n=read();m=read();T=read();
for(int i=1;i<=m;i++)
{
int u=read(),v=read(),w=read();
u++;v++;
insert(u,v,w);
}
if(mod==-1)puts("Impossible");
else if(spfa())puts("Possible");
else puts("Impossible");
}
return 0;
}