[羅区P4436] HNOI / AHOI2018ゲーム

問題の説明

小さなジオキャッシングの小さいG及びHは、行におけるn部屋があり、1,2、...、N、隣接する部屋の間のドアを有している番号。ドアの一部ロック解除(扉を開くために、対応するキーのための必要性)は、ドアの残りの部分は直接開くことができます。今、どの部屋(各ロックのみ対応するキー)p倍へと指示内のすべてのロックに少し小さいG Hキーを教えて:最初の時間は、私はより小さなH作る\(S_Iを\)始めの部屋(T_I \)\部屋を。しかし、小さなGは時々故意に行き止まりのコマンドに入れ、小さなHは試すために余分な力を無駄にしたくないので、毎回パス明確な指示があるかどうか事前に調査したいと思います。

あなたは小さなHとしてそれに答えることができますか?

入力形式

N、M、P、Nの代表室、ロックドアをM、およびP質問:3つの数字の最初の行。2つの数xの次のmライン、部屋内のキーのX + YのX 1のY代表。私は2つの整数の行である次のP行、\(S_I、T_I \)は、要求の代わりに、。

出力フォーマット

P出力線は、それぞれ、「YES」または「NO」の行、または到達できない表します。

サンプル入力

5 4
1 3
2 2
3 1
4 4
2 5
3 5
4 5
2 1
3 1

サンプル出力

YES
NO
YES
YES
NO

説明

解決

それは、私は、地域に到達する最後のいくつかの区間[李は、R]にする必要があり、各点のために見つけることができます。問題は、これらの間隔を見つける方法です。

ドアの左側にあるドアの鍵た場合は、ドアの右側から通過しませんが、右側のこの扉は、左から通過しない場合。我々は、エッジに到達する到達していないことにより、各ドアの両側にあるのであれば、範囲の間隔で見つけることができ、この時点で(そこだけ前側が点に接続されているトポロジから得られた点列の前の点であってもよいしなければなりませんこの時点)。だから、あなたはトポロジカル整列、チームの最初のポイントを使用することができ、拡張左から右への扉マイナス1の右側のドアの数に等しい注意、特定のコードを参照してくださいポイントの数を拡大しました。

しかし、範囲の可能な相互作用は、リングにそこに接続することができるので、そのトポロジカルソートは意味がありません。したがって、最初は、断面の前処理が可能である必要があり、この範囲の点に縮小しました。すべての情報は、縮小後の時点に更新されている間。

問い合わせへの対応、あなたは単純にSへのの範囲内のTかどうかを判断することができます。

コード

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#define N 1000002
#define M 1000002
using namespace std;
int head[N],ver[M],nxt[M],d[N],t;
int n,m,q,i,x[N],y[N],pos[N],cnt=1,gap[N],l[N],r[N];
bool lock[N];
int read()
{
    char c=getchar();
    int w=0;
    while(c<'0'||c>'9') c=getchar();
    while(c<='9'&&c>='0'){
        w=w*10+c-'0';
        c=getchar();
    }
    return w;
}
void insert(int x,int y)
{
    t++;
    ver[t]=y;
    nxt[t]=head[x];
    head[x]=t;
    d[y]++;
}
bool check(int x,int y)
{
    if(y==0||y==cnt+1) return 0;
    if(x<y) y--;
    return l[x]<=pos[y]&&pos[y]<=r[x];//钥匙是否在当前可达区间中
}
void toposort()
{
    queue<int> q;
    for(int i=1;i<=cnt;i++){
        if(d[i]==0) q.push(i);
    }
    while(!q.empty()){
        int x=q.front();
        q.pop();
        bool flag=1;
        while(flag){
            flag=0;
            while(check(x,l[x]-1)) l[x]=l[l[x]-1],flag=1;//可以就更新为左边的左端点
            while(check(x,r[x]+1)) r[x]=r[r[x]+1],flag=1;//更新为右边的右端点
        }
        for(int i=head[x];i;i=nxt[i]){
            int y=ver[i];
            d[y]--;
            if(d[y]==0) q.push(y);
        }
    }
}
int main()
{
    n=read();m=read();q=read();
    for(i=1;i<=m;i++){
        x[i]=read();y[i]=read();
        lock[x[i]]=1;
    }
    lock[n]=1;
    for(i=1;i<=n;i++){
        gap[i]=cnt;
        if(lock[i]){
            l[cnt]=r[cnt]=cnt;
            cnt++;
        }
    }
    cnt--;
    for(i=1;i<=m;i++){
        int tx=gap[x[i]],ty=gap[y[i]];
        pos[tx]=ty;
        if(ty<=tx) insert(tx+1,tx);
        else insert(tx,tx+1);
    }
    toposort();
    for(i=1;i<=q;i++){
        int x=read(),y=read();
        x=gap[x],y=gap[y];
        if(l[x]<=y&&y<=r[x]) puts("YES");
        else puts("NO");
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/LSlzf/p/11669096.html