BZOJ 4025二部図。

私は良いタイトルがoierを繰り出されると聞きました

問題の意味

Mエッジn個の点、合計時間はTです。

毎日時間が存在しますが。たびに、私は数字が二部グラフであるかどうか、尋ねました。

問題解決のためのアイデア

グラフ理論を学んだ、私たちは、グラフが、彼は奇妙なリングをした場合に限り、二部グラフであることを知っています。

2つの点が何もない場合明らかに、我々は関係なく、他の条件の、ここで側に直接接続することができます。だから我々は互いに素セットを知っている必要があります。

私は側は、その後、自閉症消え見始めました。

dalaoアドバイスの後、と呼ばれる一種見つける取消互いに素セットの事を。

ツリーセグメントのログN個のノードのように表すことができる各側は、アカウントに現在時刻を取ります。

再びツリー線を横断し、現在のノードを添加しました。彼の息子、その後取り消された側についての再帰的。

暴力奇数リングジャンプを検討する裁判官は、ハングします。ヒューリスティックマージのセット。

ヒューリスティック合併は、ルートとルート側との間に接続する必要がありますので、私たちは少しでもエッジ、変更されたエッジの重みに対処するつもりだ、エッジに直接同等に接続することができます。

コード

#include<bits/stdc++.h>
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
using namespace std;
const int sz=2e5+527;
int n,m,T;
int dep[sz],f[sz],d[sz];
queue<int>q[sz<<1];
int getfa(int x) { return x==f[x]?x:getfa(f[x]); }
int getdis(int x) { return x==f[x]?0:d[x]^getdis(f[x]); }
struct Edge{
    int u,v,w;
}e[sz];
void insert(int o,int l,int r,int x,int y,int num){
    if(x<=l&&r<=y) return (void)(q[o].push(num));
    int mid=(l+r)>>1;
    if(x<=mid) insert(lson,x,y,num);
    if(mid<y) insert(rson,x,y,num);
}
void resum(stack<Edge>S){
    while(!S.empty()){
        d[f[S.top().u]=S.top().u]=0;
        dep[S.top().v]-=S.top().w;
        S.pop();
    }
}
void solve(int o,int l,int r){
    stack<Edge>S;
    while(!q[o].empty()){
        int num=q[o].front();
        q[o].pop();
        int x=e[num].u,y=e[num].v;
        int fx=getfa(x),fy=getfa(y);
        int w=getdis(x)^getdis(y)^1;
        if(fx==fy&&w){
            for(int i=l;i<=r;i++) puts("No");
            return (void)(resum(S));
        }
        if(fx!=fy){
            if(dep[fx]>dep[fy]) swap(fx,fy),swap(x,y);
            Edge cur=(Edge){fx,fy,0};
            f[fx]=fy,d[fx]=w;
            if(dep[fx]==dep[fy]) ++dep[fy],cur.w=1;
            S.push(cur);
        }
    }
    if(l==r){ resum(S);return (void)(puts("Yes")); }
    int mid=(l+r)>>1;
    solve(lson);
    solve(rson);
    resum(S);
}
int main(){
    scanf("%d%d%d",&n,&m,&T);
    int u,v,L,R;
    for(int i=1;i<=n;i++) f[i]=i;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d%d",&u,&v,&L,&R);
        L++;
        e[i]=(Edge){u,v,1};
        insert(1,1,T,L,R,i);
    }
    solve(1,1,T);
}

おすすめ

転載: www.cnblogs.com/river-flows-in-you/p/11286120.html