Hdu2437-Jerboas(取余数判重搜索)

Jerboas are small desert-living animals, which resemble mice with a long tufted tail and very long hind legs. Jerboas shelter in well-hidden burrows. They create two types of burrow: temporary and permanent. The temporary burrows are plain tubes while the permanent burrows are sealed with a plug of sand to keep heat out and moisture in.

As far as we know, jerboa burrows in the desert are connected with one-way tunnels. What‘s more, for some unknown reasons, it‘s true that start from any burrow, follows the tunnels you can not go back to the starting burrow.       Summer means last-minute of offers on good times, so of course jerboas could not stay behind. One day, a little jerboa Alice who lived in a temporary burrow S wants to migrate to a permanent one. There are different routes she can take, but Alice is so odd that she only selects those whose total travel distances is a multiple of K. Among all routes that Alice may select, we are interested in the shortest one. Can you help to find it out? Of course different routes may lead to different destinations.

Input

On the first line of input, there is a single positive integer T <= 20 specifying the number of test cases to follow.
      Each test case starts with four integers in the first line: N, M, S, K.       N is the number of burrows in the desert (burrows are numbered with 1, 2, …, N);       M is the number of tunnels connecting the burrows;
      S is where Alice lived and K is as described above. (0 < N <= 1000, 0 <= M <= 20000, 0 < S <= N, 0 < K <= 1000)       The second line contains N characters each could be ‘T’ or ‘P’. The i-th character specifying the type of the burrow i. ‘T’ means temporary burrow, ‘P’ means permanent burrow. It’s guaranteed that the S-th character is ‘T’.       Next follow M lines, each line with 3 integers A, B, C. Specifying that there is a tunnel from burrow A to burrow B, and its length is C. (0 < A, B <= N, A != B, 0 < C < 40000)

Output

For each test case you should output a single line containing "Case X: Y Z" (quotes for clarity) where X is the number of the test case (starting at 1) and Y is the length of the shortest route Alice can select and Z is the destination of the selected route.       Notice that burrow Z should be a permanent burrow.       In case there’s more than one solution, Z should be the minimum.       In case there‘s no solution, Y and Z should be both equal to -1.

Sample Input

2

5 5 1 7

TPPTP

1 2 8

1 4 7

4 3 9

2 3 6

1 5 3

5 5 1 7

TPTTP

1 2 8

1 4 7

4 3 9

2 3 6

1 5 3

Sample Output

Case 1: 14 3

Case 2: -1 -1

题意:简单点说就是有N个点M条边,有些点是T(temporary  burrow),有些点是P(permanent burrow).给出起点,要找到一个P点,而且路径长度恰好是K的倍数。

尽量找路径长度短的,如果有两个路径长度相同的,则取字典序小的。

解析:优先队列,总是先取出路径长度小的,因为K最大只有1000,取余数,用vis[余数][点的编号]保存状态,为甚么这样标记是正确的,因为优先队列就已经保证先被

标记的状态路径长度就已经是最小的了。

代码

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<utility>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<iterator>
#include<stack>
using namespace std;
const int INF=1e9+7;
const double eps=1e-7;
const int maxn=1005;
int N,M,start,mod;
bool vis[maxn][maxn];
char road[maxn];
struct node
{
    int val,rest,pos;
    node(int val=0,int rest=0,int pos=0):val(val),rest(rest),pos(pos){}
    bool operator < (const node& t) const{ return val>t.val; }
};
priority_queue<node> que;
struct edge
{
    int u,v,c;
    edge(int u=0,int v=0,int c=0):u(u),v(v),c(c){}
};
vector<edge> G[maxn];
void init()
{
    while(!que.empty()) que.pop();
    for(int i=0;i<maxn;i++) G[i].clear();
    memset(vis,false,sizeof(vis));
}
void solve()
{
    int ansl=INF,ansp=-1;
    que.push(node(0,0,start));
    vis[0][start]=true;
    while(!que.empty())
    {
        node t=que.top();  que.pop();
        int val=t.val,rest=t.rest,pos=t.pos;
        if(val>ansl) break; //路径长度大了
        if(rest==0&&road[pos]==‘P‘)  //是P点更新答案
        {
            if(val<ansl||(val==ansl&&pos<ansp))
            {
                ansl=val;
                ansp=pos;
            }
        }
        int Size=G[pos].size();
        for(int i=0;i<Size;i++)
        {
            edge& e=G[pos][i];
            int v=e.v,c=e.c+val;
            if(vis[c%mod][v]) continue;
            vis[c%mod][v]=true;
            que.push(node(c,c%mod,v));
        }
    }
    if(ansp==-1) printf("-1 -1\n");
    else printf("%d %d\n",ansl,ansp);
}
int main()
{
    int T,Case=0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d",&N,&M,&start,&mod);
        scanf("%s",road+1);   //输入
        init();
        int u,v,c;
        while(M--)
        {
            scanf("%d%d%d",&u,&v,&c);
            G[u].push_back(edge(u,v,c));//边
        }
        printf("Case %d: ",++Case);
        solve();
    }
    return 0;
}
时间: 2024-08-02 12:31:25

Hdu2437-Jerboas(取余数判重搜索)的相关文章

hdu 1226 超级密码 bfs+取余判重

超级密码 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 2808    Accepted Submission(s): 897 Problem Description Ignatius花了一个星期的时间终于找到了传说中的宝藏,宝藏被放在一个房间里,房间的门用密码锁起来了,在门旁边的墙上有一些关于密码的提示信息: 密码是一个C进制的

HDU 4474&amp;&amp;POJ 1465 BFS&amp;&amp;余数判重

两道题只是输入输出格式略有不同 给出n,m,m个数 要求生成一个数x,是n的倍数,并且只由这M个数构成(或不能含有这M个数中的任意一个),求最小的x,没有则输出-1(0): BFS找每一个满足n的倍数的数,用余数判重优化 对于给定两个数A,B,如果A和B模N都相同,设为C,即: A=x*N+C B=y*N+C 那么如果在A后面加上一个数字能够被N整除,则在B后面加上这个数字也肯定可以被N整除 即:(A*10+X)%N==(B*10+X)%N 因此可以利用模N的结果进行判重,只保留相同余数的最小数

poj1465Multiple(经典BFS+余数判重)

Multiple Time Limit: 1000MS   Memory Limit: 32768K Total Submissions: 6936   Accepted: 1495 Description a program that, given a natural number N between 0 and 4999 (inclusively), and M distinct decimal digits X1,X2..XM (at least one), finds the small

[bfs+余数判重+路径记录] hdu 4474 Yet Another Multiple Problem

题意: 给一个n和m个数字(一位数) 求最小的n的倍数不含有这m个数字,不存在输出-1 思路: 首先有可能这个数超long long 所以无法暴力解决 所以这题应该是一个bfs 为什么能用余数判重呢 对于当前的余数进到队列里,一定是这个余数对应数的最小值 接下来再怎么添加到满足条件的后续东西应该是一样的 所以就可以余数判重了,类似数位dp的记录方式 然后再加上一个路径记录就好了 代码: #include"cstdlib" #include"cstdio" #incl

HDU 2579 Dating with girls(2) BFS 余数判重

对于石头的处理就按照每个位置的时间取k的余数判一下重复就好,其他随意写 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <string> #include <queue> #include <deque> #include

八数码问题+路径寻找问题+bfs(隐式图的判重操作)

Δ路径寻找问题可以归结为隐式图的遍历,它的任务是找到一条凑够初始状态到终止问题的最优路径, 而不是像回溯法那样找到一个符合某些要求的解. 八数码问题就是路径查找问题背景下的经典训练题目. 程序框架 process()  初始化vis数组,初始化初始节点到目标节点的移动距离 dfs()搜索到每一个节点,如果不是目标节点,对其依次扩展所有子节点,并判重,全部子节点搜索完全后,改变父节点:如果是目标节点成功返回 输出最少移动步数 input: 2 6 4 1 3 7 0 5 8 8 1 5 7 3 6

数的拆分x有一布判重特别重要!

qwqx 突然想起要打上题目 任何一个大于1的自然数n,总可以拆分成若干个小于n的自然数之和. 当n=7共14种拆分方法: 7=1+1+1+1+1+1+1 7=1+1+1+1+1+2 7=1+1+1+1+3 7=1+1+1+2+2 7=1+1+1+4 7=1+1+2+3 7=1+1+5 7=1+2+2+2 7=1+2+4 7=1+3+3 7=1+6 7=2+2+3 7=2+5 7=3+4 total=14 //AC自动机x#include<iostream>#include<cstdio

poj1840Eqs(哈希判重)

题目链接: 传送门 思路: 这道题是一个简单的hash的应用,如果直接暴力的话肯定承受不了5重for循环,所以比赛的时候我先到分成两组,但是后来用到了许多数组,然后想到数字太大,还先到stl判重, 后来搞出来还是在本地跑的很慢,就放弃了..后来看到题解,不得不说太牛了,我的思路是对的,首先把方程分成左右两边,然后分别暴力,因为计算结果的上限可能达到 50*50*50*50*2=1250000,所以取值范围为-12500000--12500000,所以为了避免冲突,应该将hash数组开到2*125

HDU2579--Dating with girls(2)--(DFS, 判重)

Dating with girls(2) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1418    Accepted Submission(s): 393 Problem Description If you have solved the problem Dating with girls(1).I think you can