zoukankan      html  css  js  c++  java
  • bzoj2725: [Violet 6]故乡的梦&&bzoj4400: tjoi2012 桥

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2725

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

    思路:首先随便找到一条最短路

    如果删除一条边(x,y),那么最短路就会绕开x和y走一段

    即S->最短路上的一个点->不在最短路的某些边->最短路上的一个点->T

    对于每个不在选定的最短路上的点,求出fs[x]表示S到x的最短路在哪个点脱离选定的最短路

    ft[y]表示从y到T的最短路在哪个点进入选定的最短路

    即S->fs[x]->x->y->ft[y]->T

    那么对于一条不在最短路的边,它就有可能在删去fs[x]与ft[y]之间的最短路边时发挥作用

    记录ans[i]表示最短路上第i条边删去后的答案

    处理每条不在最短路上的边,就在线段树上对fs[x]到ft[y]这段区间覆盖取min即可。

    4400类似,因为找fs和ft时没有判是否已经找过,直接被卡T,上pbds都没用.


    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define ls (p<<1)
    #define rs ((p<<1)|1)
    #define mid ((l+r)>>1)
    #define mp(a,b) make_pair(a,b)
    #define dist first
    #define id second
    #define abs(a) (a>0?a:-(a))
    typedef long long ll;
    const int maxn=200010,maxm=400010;
    using namespace std;
    typedef pair<ll,int> PI;
    int pre[maxm],now[maxn],son[maxm],tot,n,m,Q,S,T,pos[maxn],len,idx[maxn],fs[maxn],ft[maxn];
    ll ds[maxn],dt[maxn],inf,ans[maxn],val[maxm];
    struct Edge{int u,v;ll w;}E[maxm];
    struct Tsegment{
    	ll cov[maxn<<2],v[maxn<<2];
    	void cover(int p,ll va){v[p]=min(v[p],va),cov[p]=min(cov[p],va);}
    	void down(int p){if (cov[p]!=inf) cover(ls,cov[p]),cover(rs,cov[p]),cov[p]=inf;}
    	void build(int p,int l,int r){
    		cov[p]=v[p]=inf;if (l==r) return;
    		build(ls,l,mid),build(rs,mid+1,r);
    	}
    	void modify(int p,int l,int r,int a,int b,ll va){
    		if (l==a&&r==b){cover(p,va);return;}
    		down(p);
    		if (b<=mid) modify(ls,l,mid,a,b,va);
    		else if (a>mid) modify(rs,mid+1,r,a,b,va);
    		else modify(ls,l,mid,a,mid,va),modify(rs,mid+1,r,mid+1,b,va);
    	}
    	void query(int p,int l,int r){
    		if (l==r){ans[l]=v[p];return;}
    		down(p),query(ls,l,mid),query(rs,mid+1,r);
    	}
    	void modify(int l,int r,ll va){modify(1,1,len-1,l,r,va);}
    	void query(){query(1,1,len-1);}
    }Tree;
    priority_queue<PI,vector<PI>,greater<PI> > q;
    int que[maxm+10],head,tail;bool vis[maxn];
    bool inpath(int x,int y){return pos[x]&&pos[y]&&abs(pos[x]-pos[y])==1;}
    void add(int a,int b,ll c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
    
    void dijkstra(int s,ll dis[]){
    	q.push(mp(dis[s]=0,s)),inf=dis[0];
    	while (!q.empty()){
    		PI x=q.top();q.pop();
    		for (int y=now[x.id];y;y=pre[y])
    			if (x.dist+val[y]<dis[son[y]])
    				q.push(mp(dis[son[y]]=x.dist+val[y],son[y]));
    	}
    }
    
    void getway(){
    	for (int x=S,last=-1;;){
    		pos[x]=++len,idx[len]=x;
    		if (x==T) break;
    		for (int y=now[x];y;y=pre[y])
    			if (son[y]!=last&&ds[x]+val[y]+dt[son[y]]==ds[T]){last=x,x=son[y];break;}
    	}
    }
    
    void getfir(int s,ll dis[],int fir[]){
    	que[tail=1]=s,fir[s]=s,head=0;
    	while (head!=tail){
    		int x=que[++head>maxm?1:head];
    		for (int y=now[x];y;y=pre[y])
    			if (!pos[son[y]]&&!fir[son[y]]&&dis[son[y]]==dis[x]+val[y])//要判!fir[son[y]]
    				que[++tail>maxm?1:tail]=son[y],fir[son[y]]=s;
    	}
    }
    
    int main(){
    	scanf("%d%d",&n,&m);ll z;
    	for (int i=1,x,y;i<=m;i++) scanf("%d%d%lld",&x,&y,&z),E[i]=(Edge){x,y,z},add(x,y,z),add(y,x,z);
    	scanf("%d%d%d",&S,&T,&Q);
    	memset(ds,63,sizeof(ds)),dijkstra(S,ds);
    	if (ds[T]==inf){
    		for (int i=1;i<=Q;i++) puts("Infinity");
    		return 0;
    	}
    	memset(dt,63,sizeof(dt)),dijkstra(T,dt),getway();
    	for (int i=1;i<=len;i++) getfir(idx[i],ds,fs);
    	for (int i=len;i;i--) getfir(idx[i],dt,ft);
    	Tree.build(1,1,len-1);
    	for (int i=1;i<=m;i++){
    		int u=E[i].u,v=E[i].v;ll w=E[i].w;
    		if (!fs[u]||!fs[v]||inpath(u,v)) continue;
    		if (pos[fs[u]]<pos[ft[v]]) Tree.modify(pos[fs[u]],pos[ft[v]]-1,ds[u]+dt[v]+w);
    		if (pos[fs[v]]<pos[ft[u]]) Tree.modify(pos[fs[v]],pos[ft[u]]-1,ds[v]+dt[u]+w);
    	}
    	Tree.query();
    	for (int i=1,x,y;i<=Q;i++){
    		scanf("%d%d",&x,&y);
    		if (!inpath(x,y)) printf("%lld
    ",ds[T]);
    		else{
    			if (pos[x]>pos[y]) swap(x,y);
    			if (ans[pos[x]]>=inf) puts("Infinity");
    			else printf("%lld
    ",ans[pos[x]]);
    		}
    	}
    	return 0;
    }


    #include<ctime>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<ext/pb_ds/priority_queue.hpp>
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define swap(a,b) std::swap(a,b)
    #define ls (p<<1)
    #define rs ((p<<1)|1)
    #define mid ((l+r)>>1)
    #define mp(a,b) std::make_pair(a,b)
    #define dist first
    #define id second
    #define abs(a) (a>0?a:-(a))
    //typedef long long int;
    const int maxn=200010,maxm=400010;
    //using namespace std;
    typedef std::pair<int,int> PI;
    int pre[maxm],now[maxn],son[maxm],tot=1,n,m,Q,S,T,pos[maxn],len,idx[maxn],fs[maxn],ft[maxn],cnt;
    int ds[maxn],dt[maxn],inf,ans[maxn],val[maxm],res,ord[maxm];
    struct Edge{int u,v;int w;}E[maxm];
    struct Tsegment{
    	int cov[maxn<<2],v[maxn<<2];
    	void cover(int p,int va){v[p]=min(v[p],va),cov[p]=min(cov[p],va);}
    	void down(int p){if (cov[p]!=inf) cover(ls,cov[p]),cover(rs,cov[p]),cov[p]=inf;}
    	void build(int p,int l,int r){
    		cov[p]=v[p]=inf;if (l==r) return;
    		build(ls,l,mid),build(rs,mid+1,r);
    	}
    	void modify(int p,int l,int r,int a,int b,int va){
    		if (l==a&&r==b){cover(p,va);return;}
    		down(p);
    		if (b<=mid) modify(ls,l,mid,a,b,va);
    		else if (a>mid) modify(rs,mid+1,r,a,b,va);
    		else modify(ls,l,mid,a,mid,va),modify(rs,mid+1,r,mid+1,b,va);
    	}
    	void query(int p,int l,int r){
    		if (l==r){ans[l]=v[p];return;}
    		down(p),query(ls,l,mid),query(rs,mid+1,r);
    	}
    	void modify(int l,int r,int va){modify(1,1,len-1,l,r,va);}
    	void query(){query(1,1,len-1);}
    }Tree;
    using namespace __gnu_pbds;
    priority_queue<PI,std::greater<PI>,pairing_heap_tag> q;
    int que[maxm+10],head,tail;bool vis[maxn],inpath[maxm];
    void add(int a,int b,int c){pre[++tot]=now[a],now[a]=tot,son[tot]=b,val[tot]=c;}
    
    void dijkstra(int s,int dis[]){
    	q.push(mp(dis[s]=0,s)),inf=dis[0];
    	static bool upd[maxn];
    	memset(upd+1,0,sizeof(bool)*n);
    	while (!q.empty()){
    		PI x=q.top();q.pop();
    		if (upd[x.id]) continue;upd[x.id]=1;
    		for (int y=now[x.id];y;y=pre[y])
    			if (x.dist+val[y]<dis[son[y]]) 
    				q.push(mp(dis[son[y]]=x.dist+val[y],son[y]));
    	}
    }
    
    void getway(){
    	for (int x=S,last=-1;;){
    		pos[x]=++len,idx[len]=x;
    		if (x==T) break;
    		for (int y=now[x];y;y=pre[y])
    			if (son[y]!=last&&ds[x]+val[y]+dt[son[y]]==ds[T]){last=x,x=son[y],inpath[y>>1]=1;break;}
    	}
    }
    
    void getfir(int s,int dis[],int fir[]){
    	que[tail=1]=s,fir[s]=s,head=0;
    	while (head!=tail){
    		int x=que[++head>maxm?1:head];
    		for (int y=now[x];y;y=pre[y])
    			if (!pos[son[y]]&&!fir[son[y]]&&dis[son[y]]==dis[x]+val[y])
    				que[++tail>maxm?1:tail]=son[y],fir[son[y]]=s;
    	}
    }
    
    int main(){
    	//freopen("boss8.in","r",stdin);
    	scanf("%d%d",&n,&m);int z;//
    	for (int i=1,x,y;i<=m;i++){
    		scanf("%d%d%d",&x,&y,&z);
    		if (x>y) swap(x,y);
    		E[i]=(Edge){x,y,z};
    		add(x,y,z),add(y,x,z);
    	}
    	S=1,T=n;
    	memset(ds,63,sizeof(int)*(n+1)),dijkstra(S,ds);
    	memset(dt,63,sizeof(int)*(n+1)),dijkstra(T,dt);
    	getway();//int t1=(int)clock();
    	for (int i=1;i<=len;i++) getfir(idx[i],ds,fs);
    	for (int i=len;i;i--) getfir(idx[i],dt,ft);
    	//int t2=(int)clock();printf("step1 %d
    ",t2-t1);
    	Tree.build(1,1,len-1);
    	for (int i=1;i<=m;i++){
    		int u=E[i].u,v=E[i].v;int w=E[i].w;
    		if (!fs[u]||!fs[v]||inpath[i]) continue;
    		if (pos[fs[u]]<pos[ft[v]]) Tree.modify(pos[fs[u]],pos[ft[v]]-1,ds[u]+dt[v]+w);
    		if (pos[fs[v]]<pos[ft[u]]) Tree.modify(pos[fs[v]],pos[ft[u]]-1,ds[v]+dt[u]+w);
    	}
    	Tree.query();
    	//for (int i=1;i<len;i++) printf("%d
    ",ans[i]);
    	for (int i=1;i<len;i++) res=max(res,ans[i]);
    	for (int i=1;i<len;i++) cnt+=(ans[i]==res);
    	printf("%d %d
    ",res,res==ds[T]?m:cnt);//
    	return 0;
    }


  • 相关阅读:
    php趣题小记
    git常用语法
    Go 使用小记
    小程序 显示对话框 确定-取消
    小程序 后退一页
    Vue脚手架使用步骤 2.9.6版本
    小程序 后台返回的对象数组(每个数组添加一个新的属性值)
    小程序 添加对象
    小程序图表wx-chart
    微信小程序之自定义select下拉选项框组件
  • 原文地址:https://www.cnblogs.com/thythy/p/5493477.html
Copyright © 2011-2022 走看看