●BZOJ 1969 [Ahoi2005]LANE 航线规划

题链:

http://www.lydsy.com/JudgeOnline/problem.php?id=1969

题解:

线段树,树链剖分,反向考虑
思路是很巧妙,但是感觉代码真的恶心。。

反着考虑,先按照给出的操作把所有该删的边都删掉
那么剩下的也还是一个联通块。(题目保证了的)
然后在该联通块里随便选出某些边来形成一颗树。
那么显然,若只看树边的话,每一条树边都是一条关键边,
如果此时加一条其他的边 e(x,y),使得形成了一个环,
那么显然 x ~ y 路径上的边都不再是关键边。

那么此时问题变为了树上的区间覆盖问题,树链剖分+线段树来解决就好了。
(另外,会用到 hash或者 map的)

代码:(三份,分别是用到map,hash和hash表的,hahaha)

map

#include<map>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 40500
#define MAXM 100500
using namespace std;
int fa[MAXN],bgs[MAXN],top[MAXN],dep[MAXN],pos[MAXN],ord[MAXN],ANS[MAXN];
int N,M,snt,ont,ant;
typedef pair<int,int>pii;
map<pii,bool>H;
struct Oper{
	int type,x,y;
}stk[MAXN]; 
struct Edge{
	int to[MAXM*2],nxt[MAXM*2],mark[MAXM*2],head[MAXN],ent;
	Edge(){
		ent=2; memset(head,0,sizeof(head));
	}
	void Adde(int u,int v){
		to[ent]=v; nxt[ent]=head[u]; head[u]=ent++;
		to[ent]=u; nxt[ent]=head[v]; head[v]=ent++;
	}
}E;
struct SGT{
	int ls[MAXN*2],rs[MAXN*2],rem[MAXN*2],sz,rt;
	void pushup(int u){
		rem[u]=rem[ls[u]]+rem[rs[u]];
	}
	void Build(int &u,int l,int r){
		u=++sz; 
		if(l==r){rem[u]=1; return;}
		int mid=(l+r)>>1;
		Build(ls[u],l,mid);
		Build(rs[u],mid+1,r);
		pushup(u);
	}
	void Modify(int u,int l,int r,int al,int ar){
		if(!rem[u]) return;
		if(al<=l&&r<=ar){rem[u]=0; return;}
		int mid=(l+r)>>1;
		if(al<=mid) Modify(ls[u],l,mid,al,ar);
		if(mid<ar) Modify(rs[u],mid+1,r,al,ar);
		pushup(u);
	}
	int Query(int u,int l,int r,int al,int ar){
		if(!rem[u]) return 0;
		if(al<=l&&r<=ar) return rem[u];
		int mid=(l+r)>>1,ret=0;
		if(al<=mid) ret+=Query(ls[u],l,mid,al,ar);
		if(mid<ar) ret+=Query(rs[u],mid+1,r,al,ar);
		return ret;
	}
}DT;
void read(int &x){
	static int f; static char ch;
	x=0; f=1; ch=getchar();
	while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();}
	while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	x=x*f;
}
int dfs1(int u,int dad){
	static bool vis[MAXN];
	int bgn=0,num=1,son; vis[u]=1; fa[u]=dad;
	for(int i=E.head[u],v;i;i=E.nxt[i]){
		v=E.to[i]; if(vis[v]) continue;
		if(H[make_pair(u,v)]) continue;
		E.mark[i]=1; E.mark[i^1]=1; 
		son=dfs1(v,u); 
		if(bgn<son) bgn=son,bgs[u]=v;
		num+=son;
	}
	return num;
}
void dfs2(int u,int tp){
	ord[++ont]=u; pos[u]=ont;
	top[u]=tp; dep[u]=dep[fa[u]]+1;
	if(bgs[u]) dfs2(bgs[u],tp);
	for(int i=E.head[u],v;i;i=E.nxt[i]) if(E.mark[i]){
		v=E.to[i]; 
		if(v==bgs[u]||v==fa[u]) continue;
		dfs2(v,v);
	}
}
void cover(int u,int v){
	while(top[u]!=top[v]){
		if(dep[top[u]]>dep[top[v]]) swap(u,v);
		DT.Modify(DT.rt,1,N,pos[top[v]],pos[v]);
		v=fa[top[v]];
	}
	if(u==v) return;
	if(dep[u]>dep[v]) swap(u,v);
	DT.Modify(DT.rt,1,N,pos[u]+1,pos[v]);
}
int answer(int u,int v){
	int ret=0;
	while(top[u]!=top[v]){
		if(dep[top[u]]>dep[top[v]]) swap(u,v);
		ret+=DT.Query(DT.rt,1,N,pos[top[v]],pos[v]);
		v=fa[top[v]];
	}
	if(u==v) return ret;
	if(dep[u]>dep[v]) swap(u,v);
	ret+=DT.Query(DT.rt,1,N,pos[u]+1,pos[v]);
	return ret;
}
int main(){
	//freopen("1969.out","w",stdout);
	read(N); read(M);
	for(int i=1,u,v;i<=M;i++)
		read(u),read(v),E.Adde(u,v);
	while(1){
		read(stk[snt+1].type); if(stk[snt+1].type==-1) break;
		snt++; read(stk[snt].x); read(stk[snt].y);
		if(stk[snt].type) continue;
		H[make_pair(stk[snt].x,stk[snt].y)]=1;
		H[make_pair(stk[snt].y,stk[snt].x)]=1;
	}
	dfs1(1,0); 
	dfs2(1,1);
	DT.Build(DT.rt,1,N);
	for(int u=1,v;u<=N;u++)
		for(int i=E.head[u];i;i=E.nxt[i]){
			v=E.to[i]; if(u>v||E.mark[i]) continue;
			if(H[make_pair(u,v)]) continue;
			cover(u,v);
		}
	while(snt){
		if(stk[snt].type) ANS[++ant]=answer(stk[snt].x,stk[snt].y);
		else cover(stk[snt].x,stk[snt].y);
		snt--;
	}
	while(ant) printf("%d\n",ANS[ant--]);
	return 0;
}

hash

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 40500
#define MAXM 100500
using namespace std;
int fa[MAXN],bgs[MAXN],top[MAXN],dep[MAXN],pos[MAXN],ord[MAXN],ANS[MAXN];
int N,M,snt,ont,ant;
struct Oper{
    int type,x,y;
}stk[MAXN]; 
struct Edge{
    int to[MAXM*2],nxt[MAXM*2],mark[MAXM*2],head[MAXN],ent;
    Edge(){
        ent=2; memset(head,0,sizeof(head));
    }
    void Adde(int u,int v){
        to[ent]=v; nxt[ent]=head[u]; head[u]=ent++;
        to[ent]=u; nxt[ent]=head[v]; head[v]=ent++;
    }
}E;
struct Hash{
    long long C[MAXN];int cnt;
    void Push(int a,int b){
        if(a>b) swap(a,b);
        C[++cnt]=(1ll*a<<30)+b;
    }
    void Finish(){
        sort(C+1,C+cnt+1);
    }
    bool Exist(int a,int b){
        static int p; static long long w;
        if(a>b) swap(a,b);
        w=(1ll*a<<30)+b;
        p=lower_bound(C+1,C+cnt+1,w)-C;
        return C[p]==w;
    }
}H;
struct SGT{
    int ls[MAXN*2],rs[MAXN*2],rem[MAXN*2],sz,rt;
    void pushup(int u){
        rem[u]=rem[ls[u]]+rem[rs[u]];
    }
    void Build(int &u,int l,int r){
        u=++sz; 
        if(l==r){rem[u]=1; return;}
        int mid=(l+r)>>1;
        Build(ls[u],l,mid);
        Build(rs[u],mid+1,r);
        pushup(u);
    }
    void Modify(int u,int l,int r,int al,int ar){
        if(!rem[u]) return;
        if(al<=l&&r<=ar){rem[u]=0; return;}
        int mid=(l+r)>>1;
        if(al<=mid) Modify(ls[u],l,mid,al,ar);
        if(mid<ar) Modify(rs[u],mid+1,r,al,ar);
        pushup(u);
    }
    int Query(int u,int l,int r,int al,int ar){
        if(!rem[u]) return 0;
        if(al<=l&&r<=ar) return rem[u];
        int mid=(l+r)>>1,ret=0;
        if(al<=mid) ret+=Query(ls[u],l,mid,al,ar);
        if(mid<ar) ret+=Query(rs[u],mid+1,r,al,ar);
        return ret;
    }
}DT;
void read(int &x){
    static int f; static char ch;
    x=0; f=1; ch=getchar();
    while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();}
    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    x=x*f;
}
int dfs1(int u,int dad){
    static bool vis[MAXN];
    int bgn=0,num=1,son; vis[u]=1; fa[u]=dad;
    for(int i=E.head[u],v;i;i=E.nxt[i]){
        v=E.to[i]; if(vis[v]) continue;
        if(H.Exist(u,v)) continue;
        E.mark[i]=1; E.mark[i^1]=1; 
        son=dfs1(v,u); 
        if(bgn<son) bgn=son,bgs[u]=v;
        num+=son;
    }
    return num;
}
void dfs2(int u,int tp){
    ord[++ont]=u; pos[u]=ont;
    top[u]=tp; dep[u]=dep[fa[u]]+1;
    if(bgs[u]) dfs2(bgs[u],tp);
    for(int i=E.head[u],v;i;i=E.nxt[i]) if(E.mark[i]){
        v=E.to[i]; 
        if(v==bgs[u]||v==fa[u]) continue;
        dfs2(v,v);
    }
}
void cover(int u,int v){
    while(top[u]!=top[v]){
        if(dep[top[u]]>dep[top[v]]) swap(u,v);
        DT.Modify(DT.rt,1,N,pos[top[v]],pos[v]);
        v=fa[top[v]];
    }
    if(u==v) return;
    if(dep[u]>dep[v]) swap(u,v);
    DT.Modify(DT.rt,1,N,pos[u]+1,pos[v]);
}
int answer(int u,int v){
    int ret=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]>dep[top[v]]) swap(u,v);
        ret+=DT.Query(DT.rt,1,N,pos[top[v]],pos[v]);
        v=fa[top[v]];
    }
    if(u==v) return ret;
    if(dep[u]>dep[v]) swap(u,v);
    ret+=DT.Query(DT.rt,1,N,pos[u]+1,pos[v]);
    return ret;
}
int main(){
    //freopen("1969.out","w",stdout);
    read(N); read(M);
    for(int i=1,u,v;i<=M;i++)
        read(u),read(v),E.Adde(u,v);
    while(1){
        read(stk[snt+1].type); if(stk[snt+1].type==-1) break;
        snt++; read(stk[snt].x); read(stk[snt].y);
        if(stk[snt].type) continue;
        H.Push(stk[snt].x,stk[snt].y);
    }
    H.Finish();
    dfs1(1,0); 
    dfs2(1,1);
    DT.Build(DT.rt,1,N);
    for(int u=1,v;u<=N;u++)
        for(int i=E.head[u];i;i=E.nxt[i]){
            v=E.to[i]; if(u>v||E.mark[i]) continue;
            if(H.Exist(u,v)) continue;
            cover(u,v);
        }
    while(snt){
        if(stk[snt].type) ANS[++ant]=answer(stk[snt].x,stk[snt].y);
        else cover(stk[snt].x,stk[snt].y);
        snt--;
    }
    while(ant) printf("%d\n",ANS[ant--]);
    return 0;
}

hash表(第一次写哈希表)

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 40500
#define MAXM 100500
using namespace std;
int fa[MAXN],bgs[MAXN],top[MAXN],dep[MAXN],pos[MAXN],ord[MAXN],ANS[MAXN];
int N,M,snt,ont,ant;
struct Oper{
    int type,x,y;
}stk[MAXN]; 
struct Edge{
    int to[MAXM*2],nxt[MAXM*2],mark[MAXM*2],head[MAXN],ent;
    Edge(){ent=2;}
    void Adde(int u,int v){
        to[ent]=v; nxt[ent]=head[u]; head[u]=ent++;
        to[ent]=u; nxt[ent]=head[v]; head[v]=ent++;
    }
}E;
struct Hash{
    int to1[MAXN],to2[MAXN],nxt[MAXN],head[50000],ent,BIT,MOD;
    Hash(){BIT=12356789; MOD=43517; ent=2;}
    void Push(int a,int b){
		static int u;
		if(a>b) swap(a,b);
        u=(1ll*a*BIT+b)%MOD;
        to1[ent]=a; to2[ent]=b; 
		nxt[ent]=head[u]; head[u]=ent++;
    }
    bool Exist(int a,int b){
        static int u;
        if(a>b) swap(a,b);
        u=(1ll*a*BIT+b)%MOD;
        for(int i=head[u];i;i=nxt[i])
        	if(to1[i]==a&&to2[i]==b) return 1;
        return 0;
    }
}H;
struct SGT{
    int ls[MAXN*2],rs[MAXN*2],rem[MAXN*2],sz,rt;
    void pushup(int u){
        rem[u]=rem[ls[u]]+rem[rs[u]];
    }
    void Build(int &u,int l,int r){
        u=++sz; 
        if(l==r){rem[u]=1; return;}
        int mid=(l+r)>>1;
        Build(ls[u],l,mid);
        Build(rs[u],mid+1,r);
        pushup(u);
    }
    void Modify(int u,int l,int r,int al,int ar){
        if(!rem[u]) return;
        if(al<=l&&r<=ar){rem[u]=0; return;}
        int mid=(l+r)>>1;
        if(al<=mid) Modify(ls[u],l,mid,al,ar);
        if(mid<ar) Modify(rs[u],mid+1,r,al,ar);
        pushup(u);
    }
    int Query(int u,int l,int r,int al,int ar){
        if(!rem[u]) return 0;
        if(al<=l&&r<=ar) return rem[u];
        int mid=(l+r)>>1,ret=0;
        if(al<=mid) ret+=Query(ls[u],l,mid,al,ar);
        if(mid<ar) ret+=Query(rs[u],mid+1,r,al,ar);
        return ret;
    }
}DT;
void read(int &x){
    static int f; static char ch;
    x=0; f=1; ch=getchar();
    while(ch<'0'||'9'<ch){if(ch=='-')f=-1;ch=getchar();}
    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    x=x*f;
}
int dfs1(int u,int dad){
    static bool vis[MAXN];
    int bgn=0,num=1,son; vis[u]=1; fa[u]=dad;
    for(int i=E.head[u],v;i;i=E.nxt[i]){
        v=E.to[i]; if(vis[v]) continue;
        if(H.Exist(u,v)) continue;
        E.mark[i]=1; E.mark[i^1]=1; 
        son=dfs1(v,u); 
        if(bgn<son) bgn=son,bgs[u]=v;
        num+=son;
    }
    return num;
}
void dfs2(int u,int tp){
    ord[++ont]=u; pos[u]=ont;
    top[u]=tp; dep[u]=dep[fa[u]]+1;
    if(bgs[u]) dfs2(bgs[u],tp);
    for(int i=E.head[u],v;i;i=E.nxt[i]) if(E.mark[i]){
        v=E.to[i]; 
        if(v==bgs[u]||v==fa[u]) continue;
        dfs2(v,v);
    }
}
void cover(int u,int v){
    while(top[u]!=top[v]){
        if(dep[top[u]]>dep[top[v]]) swap(u,v);
        DT.Modify(DT.rt,1,N,pos[top[v]],pos[v]);
        v=fa[top[v]];
    }
    if(u==v) return;
    if(dep[u]>dep[v]) swap(u,v);
    DT.Modify(DT.rt,1,N,pos[u]+1,pos[v]);
}
int answer(int u,int v){
    int ret=0;
    while(top[u]!=top[v]){
        if(dep[top[u]]>dep[top[v]]) swap(u,v);
        ret+=DT.Query(DT.rt,1,N,pos[top[v]],pos[v]);
        v=fa[top[v]];
    }
    if(u==v) return ret;
    if(dep[u]>dep[v]) swap(u,v);
    ret+=DT.Query(DT.rt,1,N,pos[u]+1,pos[v]);
    return ret;
}
int main(){
    //freopen("1969.out","w",stdout);
    read(N); read(M);
    for(int i=1,u,v;i<=M;i++)
        read(u),read(v),E.Adde(u,v);
    while(1){
        read(stk[snt+1].type); if(stk[snt+1].type==-1) break;
        snt++; read(stk[snt].x); read(stk[snt].y);
        if(stk[snt].type) continue;
        H.Push(stk[snt].x,stk[snt].y);
    }
    dfs1(1,0); 
    dfs2(1,1);
    DT.Build(DT.rt,1,N);
    for(int u=1,v;u<=N;u++)
        for(int i=E.head[u];i;i=E.nxt[i]){
            v=E.to[i]; if(u>v||E.mark[i]) continue;
            if(H.Exist(u,v)) continue;
            cover(u,v);
        }
    while(snt){
        if(stk[snt].type) ANS[++ant]=answer(stk[snt].x,stk[snt].y);
        else cover(stk[snt].x,stk[snt].y);
        snt--;
    }
    while(ant) printf("%d\n",ANS[ant--]);
    return 0;
}
posted @ 2017-12-20 21:41  *ZJ  阅读(173)  评论(0编辑  收藏  举报