NOIP模拟赛 长途旅行 (最短路spfa)

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 
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
#define pa pair
#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;
}

 

你可能感兴趣的:(ACM-图论)