隐式图搜索
对于某些状压题,转移很少,但是状态很多。
我们是无法直接判断能否转移的,因为实质上很多转移是没有必要的。
所以我们在用到这个状态的时候,枚举转移即可。这是第一次遇到。
如果以后更深的理解和好题自然会加上来。
U
v
a
658
Uva 658
Uva658
题意:有
n
n
n个
b
u
g
bug
bug,有
m
m
m个补丁。
每个补丁能够改变当前
b
u
g
bug
bug的总状态,不过也有前提条件(需要的状态)。
我们判断每次是否能够满足条件以及之后状态如何表达,在
d
i
j
dij
dij过程中枚举补丁即可(
m
m
m很小)
#include<bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;i++)
#define inf 0x3f3f3f3f3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 500050;
int n,m,limit;
int a[maxn];
int f[maxn][22];
int main(){
memset(f,0,sizeof(f));
cin>>n>>m;
limit=-1;
FOR(i,1,n){
int x,y;
scanf("%d%d",&x,&y);
a[x]=max(a[x],y);
limit=max(limit,y);
}
FOR(i,1,limit)a[i]=max(a[i-1],a[i]);
for(int i=0;i<=limit;i++)f[i][0]=a[i];
for(int j=1;j<=20;j++)
for(int i=0;i<=limit;i++){
if(f[i][j-1]==-1){
f[i][j]=-1;
continue;
}
if(f[f[i][j-1]][j-1]==f[i][j-1])f[i][j]=-1;
else f[i][j]=f[f[i][j-1]][j-1];
}
int ans,now;
for(int i=1;i<=m;i++){
int x,y;scanf("%d%d",&x,&y);
ans=0,now=x;
for(int j=20;j>=0;j--){
if(f[now][j]<=y&&f[now][j]!=-1){
ans+=1<<j;
now=f[now][j];
if(now==y)break;
}
}
if(now==y)cout<<ans<<endl;
else if(f[now][0]>y)cout<<++ans<<endl;
else puts("-1");
}
}