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
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 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
#include
#include
#include
#include
#include
#include