【Bzoj4025図二部

説明

ベンは神の持っている\(N- \)図ノードを。ベンベン側の一部の消失が表示されます後の時間T以上のように、神は、神であるため。ベン神はこの数字は二部グラフであるかどうかを各期間の必要です。神のような簡単な質問には、もちろん、ベンはするだろう、と彼はあなたをテストしたかったです。

入力

入力データの最初の行は、3つの整数である\(N- \) \(m個\) \(T \)
介して第2の行\(M + 1 \)行、各行4つの整数\(U \) \(V \) \(スタート\) \(エンド\) 最初の\(I + 1 \) 4本のラインは、整数を表し、\は、(私は\)接続されたエッジ\(U \)を\(V \) このエッジの2点、\(スタート\)は、時間的に表示され最初に\(終了\)時間で消えます。

出力

出力備える\(T \)ラインを。i行目で、最初の場合\(iは\)これは、図期間、出力に二部グラフである「\(\はい)」、そうでない場合は、出力が「\(いいえ\)引用符」、。

サンプル入力

3 3 3

1 2 0 2

2 3 0 3

1 3 1 2

サンプル出力

はい

ノー

はい

ヒント

サンプル説明:
0、両側1-2と2-3が表示されます。
第1の期間は、このグラフは二部グラフ出力である\(\はい)
1時間、1-3エッジが生じます。
第二の期間は、この図は、二部グラフ、出力ない\(いいえ\)
2時間、二辺1-2及び1-3の消失。
第3の期間は、唯一のエッジ2-3、グラフは二部グラフ出力である\(\はい)

数据范围:
\(n個の\当量100000 \)、\ (m個の\当量200000 \)、\ (T \当量100000 \)、\ (U 1 \当量、Vの\当量のn個の\)、\ (0 \当量の開始\当量のエンド\の当量T \)


考え

まず、二部グラフを決定する方法[思考]の問題である
点の数-結論所与\(\のGEQ 2 \)なし奇数リング。
かなり右感じて考えてみて、それは別の「コレクション」で奇数偶数が同じ「コレクション」の2点で、同じである任意の2点のパリティ路長の間と言うことです

だから我々は、それは二つの点に接続されていた場合、木、プラス側を維持し、その後、エッジを追加すると、二部グラフでないでない場合は2点間の距離が、現在は奇数でないかを判断することができます。

しかし、この質問は、境界消去がある、唯一のプラス側ではありません。
次に、2つのアプローチがある\(LCT \)またはセグメントツリーパーティションが。

実践:LCT

動的少しスパニングツリーを維持しています。
すべての中には、時系列順を追加します。
ノーショーリングが直接側に接続されている場合は
、リングがある場合:現在の時刻から奇数リングマークが削除の早い時間を鳴らした場合でも、リングマークなしで、「部グラフではありません」。リング側の最小時間を削除するには削除します。
エッジは関係なく、削除された場合にはボーダー消去動作は、それが削除され、削除されていません。
(しかし、私は...私はこの練習を書いていない、ただ口胡よ)

練習2:分割統治ツリーライン

時間セグメントツリーインデックス構造において、その存在の時間に各エッジをマーキング。
互いに素セットメンテナンス「木」、ちょうど各ポイントでそれを維持し、ライン上のパリティセットルートパスをチェックすると、各ノードのセグメントツリートラバーサル、。
注:
ツリーノードの発見の1のオンラインセクションでは、それはもはやダウン「しませ部グラフ」、再帰の数を表し、すべての時点で直接標識「二部グラフではありません」。
2.によりエッジ互いに素なセットを削除する、すなわち、「バックアウト」ので、パスを圧縮することができないものです。

互いに素なセットの圧縮パスなし、その都度探し\(FA \)がある\(O(LOGN)\)を探しているのは、各点\(O(LOGN)\)回、合計複雑そう\(O( nlog ^ 2n個)\)


コード

\(WA \)長い長い長い長い時間のために......
私は私が見た\(WA \)叫びを出しOOO、OOO ......

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
 
using namespace std;
 
int read(){
    int x=0;
    char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x;
}
 
const int N = 100005;
 
int n,m,T;
 
struct edge{ int u,v; }d[N*2];
int tot;
 
int root,cnt,ch[N*2][2];
vector<edge> seg[N*2];
void build(int x,int l,int r){
    if(l==r) return;
    int mid=(l+r)>>1;
    build(ch[x][0]=++cnt,l,mid);
    build(ch[x][1]=++cnt,mid+1,r);
}
void ins(int x,int l,int r,int L,int R,int c){
    if(l==L && r==R) { seg[x].push_back(d[c]); return; }
    int mid=(l+r)>>1;
    if(R<=mid) ins(ch[x][0],l,mid,L,R,c);
    else if(L>mid) ins(ch[x][1],mid+1,r,L,R,c);
    else{
        ins(ch[x][0],l,mid,L,mid,c);
        ins(ch[x][1],mid+1,r,mid+1,R,c);
    }
}
 
int ans[N],fa[N],val[N],pre[N],sz[N];
int getfa(int x) { 
    if(x==fa[x]) return x;
    int z=getfa(fa[x]);
    val[x]=val[fa[x]]^pre[x];
    return z;
}
void work(int x,int l,int r){
    int flag=1;
    vector<edge> opt;
    for(int i=0;i<seg[x].size();i++){
        int fu=getfa(seg[x][i].u),fv=getfa(seg[x][i].v);
        if(fu==fv){
            if(val[seg[x][i].u]==val[seg[x][i].v]) flag=0;
        }
        else{
            if(sz[fu]>sz[fv]) swap(fu,fv);
            fa[fu]=fv; sz[fv]+=sz[fu];
            pre[fu]=val[seg[x][i].u]^val[seg[x][i].v]^1;
            opt.push_back((edge){fu,fv});
        }
    }
     
    if(l<r && flag){
        int mid=(l+r)>>1;
        work(ch[x][0],l,mid); 
        work(ch[x][1],mid+1,r);
    }
    if(l==r) ans[l]=flag;
     
    for(int i=opt.size()-1;i>=0;i--){
        pre[opt[i].u]=val[opt[i].u]=0; //别忘了把 val 也清零!
        sz[opt[i].v]-=sz[opt[i].u];
        fa[opt[i].u]=opt[i].u;
    }
}
 
int main()
{
    int u,v,st,ed;
    n=read(); m=read(); T=read();
     
    build(root=++cnt,1,T);
    while(m--){
        u=read(); v=read(); st=read()+1; ed=read()+1;
        if(st==ed) continue;
        d[++tot]=(edge){u,v};
        ins(root,1,T,st,ed-1,tot);
    }
     
    for(int i=1;i<=n;i++) fa[i]=i,val[i]=pre[i]=0,sz[i]=1;
    work(root,1,T);
    for(int i=1;i<=T;i++)
        if(ans[i]) printf("Yes\n");
        else printf("No\n");
     
    return 0;
} 

おすすめ

転載: www.cnblogs.com/lindalee/p/11372033.html