2017ACM/ICPC亚洲区沈阳站_Infinite Fraction Path(BFS)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#define INF 0x3f3f3f3f
#define rep0(i, n) for (int i = 0; i < n; i++)
#define rep1(i, n) for (int i = 1; i <= n; i++)
#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)
#define rep_1(i, n) for (int i = n; i > 0; i--)
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define mem(x, y) memset(x, y, sizeof(x))
#define MAXN 150000 + 10
#include <queue>
/**

题目大意
一个长度为n的数列,下标 0 ~ n - 1
D[i] -> D[(i * i + 1) % n] 组成每个节点有一个出度的有向图
遍历出一条长度为n的词典序最大的路径
思路
先使序列中最大的节点入队 用两个变量ma1 ma2 
ma1 记录此层次节点的最大值(真)
ma2 记录下一层节点最大值(假)
当遍历完一层时 ma1 = m2
用book标记同层内节点不重复入队

*/
using namespace std;
typedef long long LL;
char d[MAXN];
LL n, nxt[MAXN], cnt;
int ma1, ma2;
queue< pair <LL, LL> > q;   ///层次 下标
int book[MAXN];
void work()
{
    LL step = -1;
    while (cnt < n)
    {
        pair<LL, LL> tmp = q.front();
        q.pop();
        if (tmp.first > step)
        {
            step++;
            ma1 = ma2;

            if (cnt < n)
            {
                printf("%d", ma1);
                cnt++;
            }
            ma2 = -1;
            if (d[tmp.second] - '0' == ma1)
            {
                pair<LL, LL> t;
                t.second = nxt[tmp.second];
                t.first = tmp.first + 1;
                q.push(t);
                book[t.second] = t.first;
                ma2 = d[ nxt[tmp.second] ] - '0';
            }


        }
        else if (d[tmp.second] - '0' == ma1 && d[ nxt[tmp.second] ] - '0' >= ma2 && book[nxt[tmp.second]] != tmp.first + 1)
        {
            if (d[ nxt[tmp.second] ] - '0' > ma2)
                ma2 = d[ nxt[tmp.second] ] - '0';
            pair<LL, LL> t;
            t.second = nxt[tmp.second];
            t.first = tmp.first + 1;
            book[t.second] = tmp.first + 1;
            q.push(t);
        }

    }


}


int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt", "r", stdin);
    #endif // ONLINE_JUDGE
    int t, kase = 0;
    scanf("%d", &t);
    while (t--)
    {
        //mem(book, 0);
        scanf("%lld", &n);
        scanf("%s", d);
        while (!q.empty())
            q.pop();
        ma1 = -1;
        ma2 = -1;

        for (LL i = 0; i < n; i++)
            book[i] = 0;
        for (LL i = 0; i < n; i++)
        {
            nxt[i] = (i * i + 1) % n;
            if (d[i] - '0' > ma2)
            {
                while (!q.empty())
                    q.pop();

                pair<LL, LL> tmp;
                tmp.first = 0;
                tmp.second = i;

                q.push(tmp);
                ma2 = d[i] - '0';
            }

            else if (d[i] - '0' == ma2)
            {
                pair<LL, LL> tmp;
                tmp.first = 0;
                tmp.second = i;
                q.push(tmp);
            }

        }
        cnt = 0;

        printf("Case #%d: ", ++kase);
        work();
        printf("\n");




    }


    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值