传送门: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;
}