• HDU5669-Road


    题意

    给一个(n)个点的图,标号为(1)(n),进行(m)次连边((a,b,c,d,w))

    for i in range[a,b]:
        for j in range[c,d]:
            add_edge(i,j,w)
    

    (K)次机会可以消除一条边的权值(即走过但不算),问(1)(n)的最短路。

    (nle 5 imes 10^4,mle 10^4,0le Kle 10,wle 10^3)

    分析

    (K)次消除机会用一个类似dp的东西处理(也被叫做分层图最短路),(d[i][j])表示从1走到(i)点用了(j)次机会的最短路,显然这个东西是可以dp的。现在我们只需要考虑如何求最短路。

    这个连边方式是区间对区间连同一种边,跟bzoj3218的可持久化线段树维护网络流的连边有点像。考虑线段树。

    一个区间可以表示为线段树上的最多(log n)个节点。我们一开始给线段树编号,用它来维护连边不就好啦!

    一开始是这样想的,但其实只开一颗线段树是不对的,因为无法上下走,于是取看题解。

    我们有两颗线段树,一颗连出去,一颗连入,分别称为出线段树和入线段树。出线段树的子节点连到父亲,入线段树的父亲连到子节点。然而如果只是这样的话,我们只能走一条边——从入线段树的某个点走到出线段树的点之后就回不来了!

    所以我们把入线段树的每个点连到出线段树的相同位置的点即可。

    每次连边是否需要(log ^2n)条边呢?其实不需要,我们可以对每次连边建一个中间节点,出入线段树分别连出,从这个点连入即可。

    这样总点数是(4n+m),总边数最大为(2mlog n+6n),所以使用优先队列优化Dijkstra求最短路,总复杂度为(O(Kmlog ^2n))

    这题学习了两个线段树维护出入以及中间节点减少边数的方法(可能还有分层图最短路吧)。

    代码

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<queue>
    #include<utility>
    #include<algorithm>
    using namespace std;
    int read() {
    	int x=0,f=1;
    	char c=getchar();
    	for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;
    	for (;isdigit(c);c=getchar()) x=x*10+c-'0';
    	return x*f;
    }
    const int maxn=5e4+1;
    const int maxm=1e4+1;
    const int maxp=4e5+1;
    const int maxe=2e6+1;
    const int maxk=11;
    int n,m,k,ids=0,d[maxk][maxp],inf;
    typedef pair<int,pair<int,int> > data;
    inline int Min(int &x,int y) {x=min(x,y);}
    priority_queue<data,vector<data>,greater<data> > q;
    struct Graph {
    	struct edge {
    		int v,w,nxt;
    	} e[maxe];
    	int h[maxp],tot;
    	Graph ():tot(0) {}
    	void add(int u,int v,int w) {
    		e[++tot]=(edge){v,w,h[u]};
    		h[u]=tot;
    	}
    	void dj(int S,int T) {
    		d[0][S]=0;
    		q.push(make_pair(0,make_pair(S,0)));
    		while (!q.empty()) {
    			data dat=q.top();
    			q.pop();
    			int x=dat.second.first,tim=dat.second.second;
    			for (int i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) {
    				if (tim<k && d[tim+1][v]>d[tim][x]) {
    					d[tim+1][v]=d[tim][x];
    					q.push(make_pair(d[tim+1][v],make_pair(v,tim+1)));
    				}
    				if (d[tim][v]>d[tim][x]+e[i].w) {
    					d[tim][v]=d[tim][x]+e[i].w;
    					q.push(make_pair(d[tim][v],make_pair(v,tim)));
    				}
    			}
    		}
    	}
    } G;
    struct SGT {
    	int id[maxn<<2];
    	void build(int x,int l,int r,bool op) {
    		id[x]=++ids;
    		if (l==r) return;
    		int mid=(l+r)>>1;
    		build(x<<1,l,mid,op),build(x<<1|1,mid+1,r,op);
    		op?(G.add(id[x],id[x<<1],0),G.add(id[x],id[x<<1|1],0)):(G.add(id[x<<1],id[x],0),G.add(id[x<<1|1],id[x],0));
    	}
    	void link(int x,int L,int R,int l,int r,int p,int w,bool op) {
    		if (L==l && R==r) {
    			op?G.add(p,id[x],w):G.add(id[x],p,w);
    			return;
    		}
    		int mid=(L+R)>>1;
    		if (r<=mid) link(x<<1,L,mid,l,r,p,w,op); else 
    		if (l>mid) link(x<<1|1,mid+1,R,l,r,p,w,op); else 
    		link(x<<1,L,mid,l,mid,p,w,op),link(x<<1|1,mid+1,R,mid+1,r,p,w,op);
    	}
    	int ID(int x,int l,int r,int p) {
    		if (l==r) return id[x];
    		int mid=(l+r)>>1;
    		return p<=mid?ID(x<<1,l,mid,p):ID(x<<1|1,mid+1,r,p);
    	}
    } a,b;
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("test.in","r",stdin);
    #endif
    	read(),n=read(),m=read(),k=read();
    	a.build(1,1,n,false);
    	int tmp=ids;
    	b.build(1,1,n,true);
    	for (int i=1;i<=tmp;++i) G.add(tmp+i,i,0);
    	while (m--) {
    		int l1=read(),r1=read(),l2=read(),r2=read(),w=read();
    		++ids;
    		a.link(1,1,n,l1,r1,ids,w,false);
    		b.link(1,1,n,l2,r2,ids,0,true);
    		++ids;
    		a.link(1,1,n,l2,r2,ids,w,false);
    		b.link(1,1,n,l1,r1,ids,0,true);
    	}
    	memset(d,0x3f,sizeof d),inf=d[0][0];
    	int S=a.ID(1,1,n,1),T=b.ID(1,1,n,n);
    	G.dj(S,T); // d[S][0]=0
    	int ans=inf;
    	for (int i=0;i<=k;++i) Min(ans,d[i][T]);
    	ans==inf?puts("Yww is our red sun!"):printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Android视图SurfaceView的实现原理分析
    SurfaceView
    Bitnami WordPress如何修改MySQL root的默认密码?
    Delphi XE8中Delphi和JAVA数据类型对应关系!
    Delphi XE8中Delphi和JAVA数据类型对应关系!
    Delphi XE8中Android开发有用的资源!
    Delphi XE8中Android开发有用的资源!
    Delphi XE8如何同Eclipse使用相同的Android SDK?
    关键字
    sub-G 无线芯片基础知识
  • 原文地址:https://www.cnblogs.com/owenyu/p/7154105.html
Copyright © 2020-2023  润新知