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\n",ds[T]);
		else{
			if (pos[x]>pos[y]) swap(x,y);
			if (ans[pos[x]]>=inf) puts("Infinity");
			else printf("%lld\n",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\n",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\n",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\n",res,res==ds[T]?m:cnt);//
	return 0;
}


posted @ 2016-01-10 21:58  orzpps  阅读(193)  评论(0编辑  收藏  举报