(搜索+剪枝)
题意:给定
n(n<2000000)
个点的带环单向图,每个点
i
有一个权值
这个题目有很多解法,正解是后缀数组。(目前我只想出怎么用搜索解这个题)
思路1(搜索+剪枝):
若想数字较大,那么这个数字的最高位越大越好,再是次高位,再次次高…那么我们可以先找出这些点中权值最大的点作为起始点放入队列中,然后一步步做广度优先搜索,依次排除组成数字较小的起始点。最后剩下的那个点就是答案。
但是这个肯定超时,复杂度最大为
于是朝这个方向优化:
1.同一层(step)里,我们只要那些当前权值最大的点对应的起始点。
2.对于链的分支而言:假如初始点
A
搜索到一个已经被点
3.对于环而言,假如一个点搜索了一圈最后到自身,那么我们便可以断定这个点是最优的(想想为什么)。
这三个优化缺一个都超时OTZ,折腾了我几个小时…
思路2(后缀数组):待更
思路3(暴力枚举):
仔细观察图,这个图里面环很多,暴力枚举每一个起始点,判断前几十位找出数字最大的点对应的起始点即可。
代码1:
#include <cstdio>
#include <queue>
#include <cctype>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
const int maxn = 150010;
// to whom the point blg(belong);
// rid = 1: means I can get rid of this point
int blg[maxn], rid[maxn];
int to[maxn], pre[maxn], mx_value[maxn];
char w[maxn];
struct node {
int st_pos, cur_pos;
node(int a=0, int b=0):st_pos(a),cur_pos(b){}
};
//queue<node> Q;
node Q[maxn<<1], tmp_que[maxn<<1];
int r;
void solve(int cs) {
//init
r = 0;
int n;
scanf("%d",&n); getchar();
gets(w);
for(int i=0; i<n; i++) {
int v = ((LL)i*i + 1LL) % (LL)n;
to[i] = v; pre[v] = i;
Q[r++] = node(i, i);
rid[i] = 0;
mx_value[i] = blg[i] = -1;
}
//solve
int step = 0, ans = -1;
while(r > 1) {
int sz = 0;
// find the max number in the current step
for(int i=0; i<r; i++) {
node u = Q[i];
if(rid[u.st_pos]) continue ;
if((int)w[u.cur_pos] < mx_value[step]) continue ;
if((int)w[u.cur_pos] > mx_value[step]) {
mx_value[step] = (int)w[u.cur_pos];
sz = 0;
}
int v = to[u.cur_pos];
if(blg[v] != -1) rid[blg[v]] = 1;
tmp_que[sz++] = node(u.st_pos, v);
}
// put these point into the queue again, step ++;
for(int i=0; i<sz; i++) {
Q[i] = tmp_que[i];
int last = pre[Q[i].cur_pos];
blg[last] = Q[i].st_pos;
if(Q[i].st_pos == Q[i].cur_pos) {
ans = Q[i].st_pos;
break ;
}
}
if(ans != -1) break ;
r = sz;
step ++; if(step >= n) break ;
}
// get the best starting point
node u = Q[0];
printf("Case #%d: ",cs);
int pos = u.st_pos;
if(ans != -1) pos = ans;
for(int i=0; i<n; i++) {
putchar(w[pos]);
pos = to[pos];
}
puts("");
}
int main() {
int cs, tot = 0;
scanf("%d",&cs);
while(cs --)
solve(++tot);
return 0;
}