UESTC Training for Graph Theory——J、Going back home

Going back home

Time Limit: 1000 ms Memory Limit: 65536 kB Solved: 31 Tried: 519

Description

Finally, finally this semester is over. QiQi plans to go back home.

QiQi lives in a world consist of n cities. He is currently at city S for school and about to go to city D where his home is. QiQi’s world is a little bit different from ours. In his world, one-way road collect two cities and each road is associated with a string. The time QiQi need to travel that road is the length of that string. QiQi doesn’t want to get back home too late because he missed his family so much, but not too early because he really enjoys the scenery along his trip. So he decided to go back home during the period T1 to T2.(both inclusive). As QiQi is not good at routing, he asks you to help him to come up with a perfect plan for him. You may wonder what perfect means? Because he’s too shy to say it, he lets me tell you that a perfect plan is a route that the strings along this route form a lexicographically smallest one among all legal routes, but it may not be the shortest one.

Input

The first line of the input is an integer T (T <= 30), which stands for the number of test cases you need to solve.

Every test case begins with six integers N, M, S, D, T1, T2 (2 <= N <= 50, 1 <= M <= 200, 0 <= S, D < N, S != D , 0 <= T1 <= T2 <= 2000), where N is the number of cities, M is the number of edges. S is the city which QiQi is present in, D is the city QiQi tries to reach. T1, T2 are the earliest and the latest time QiQi wants to reach his destination.

Then M lines follow. Each line contains two integers u, v and a string s which is at most 6 letters long(only lowercase latin letters). Means that there is a direct road from u to v associated with string s.(0 <= u, v < N).

Output

For every test case, you should output "Case #k: " first, where k indicates the case number and starts at 1. Then if it’s impossible to reach city D during the period T1 to T2 (both inclusive), output “Impossible”, otherwise output the route. See sample for more details.

Sample Input

2

4 4 0 3 4 4
0 1 abc
0 2 aaaa
1 3 d
2 3 d

2 1 0 1 1 4
0 1 abcde

Sample Output

Case #1: abcd
Case #2: Impossible

Source

The 9th UESTC Programming Contest Preliminary

/*算法思想:
  给一个带权图,权有两个,一个是字符串,一个是字符串的长度。让求一条路径,使得这条路径的长度介于
  T1与T2之间,并且这条路径上的字符串的字典序最小。
  感觉这是这一套题中AC的最轻松的了,但可惜是最后做的。
  我们可以从起点BFS一次,用优先队列优化。队列是一个按照路径上的字符串的字典序大小为关键子的小根堆
  我们保存到达节点 i ,总的路径长度为 j  的字符串。那么在BFS遍历的过程中,要是遍历到了目标节点,
  并且长度符合要求: [T1,T2],那么我们就可以直接输出结果,这跟 A* 有点类似。要是遍历的图中遇到状态:
  {i,j}(表示到达 i 节点,路径长度为 j)已经访问过了,那么看他路径上的字符串是否是由于访问到他时路
  径上的字符串,不是的话,这个点就不用再进队列了,如果是,就改变他的字符串的值,并且加进队列。
  如果找完了所有的状态任然找不到合法的解,那么肯定已经无解了
*/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<string>
#define N 2000
#define INF 0x7fffffff
using namespace std;
struct data
{
	int st,en,next;
	string val;
} edge[300];
int n,m,S,D,T1,T2;
int head[55],tot;
string dp[55][400];
bool vs[55][400];
struct node
{
	int v,cost;
	string route;
	bool operator < (const node &a) const
    {
        return a.route<route;
    }
};
void add_edge(int st,int en,string val)  //加边
{
    edge[tot].st=st;
	edge[tot].en=en;
	edge[tot].val=val;
	edge[tot].next=head[st];
	head[st]=tot++;
}
bool dijstra(int s,int t)  //dijstra过程
{
    priority_queue<node>q;
	q.push({s,0,""});  //初始化队列
	dp[s][0]="";
	vs[s][0]=true;
	while(!q.empty())
	{
		node now=q.top();
		q.pop();
		if(now.v==t && now.cost>=T1 && now.cost<=T2)  //这个状态合法
        {
            cout<<now.route<<endl;  //由于不知道 STL 里面的 string 到底该用什么控制符输出,就用了cout
            return true;
        }
		for(int i=head[now.v];i!=-1;i=edge[i].next)
		    if(now.cost+edge[i].val.size()<=T2 )
			{
			    if(!vs[edge[i].en][now.cost+edge[i].val.size()])  //用当前状态扩展其他的状态
			    {
			        vs[edge[i].en][now.cost+edge[i].val.size()]=true;
			        dp[edge[i].en][now.cost+edge[i].val.size()]=now.route+edge[i].val;
				    q.push({edge[i].en,now.cost+edge[i].val.size(),now.route+edge[i].val});
			    }
			    else if(dp[edge[i].en][now.cost+edge[i].val.size()]>(now.route+edge[i].val))  //如果现在的状态由于以前的状态,更新,并且加进队列中
			    {
			        dp[edge[i].en][now.cost+edge[i].val.size()]=(now.route+edge[i].val);
			        q.push({edge[i].en,now.cost+edge[i].val.size(),now.route+edge[i].val});
			    }
			}
	}
	return false;  //找不到路径
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
	{
	    scanf("%d%d%d%d%d%d",&n,&m,&S,&D,&T1,&T2);
	    tot=0;
	    memset(head,-1,sizeof(head));
        int a,b;
        char c[10];
        string C;
	    for(int i=0;i<m;i++)
	    {
		    scanf("%d%d%s",&a,&b,c);
		    C={c};
		    add_edge(a,b,C);
	    }
	    printf("Case #%d: ",ca);
		memset(vs,0,sizeof(vs));
		bool ans=dijstra(S,D);
		if(!ans) printf("Impossible\n");
	}
	return 0;
}


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值