给一幅n点m边的无向图,删一条边使从点1到点n的最短路最大,求最短路最大值,以及这种情况下可以删的边的数量。
数据保证玩家可以从岛屿1到达岛屿n。
1<=n<=100000,1<=m<=200000

建最短路树,显然必须删除最短路树上1->n路径上的一条边

考虑删了一条边后,至少要走一条不在最短路树上的边,假设它是a->b
那么最短路至少为S->a->b->t

其中S->a为起点出发的最短路树上的路径,b->t则为终点出发的。
这种情况下可能删的边满足
- 在最短路树上1->n路径上
- 不在S->a->b->t路径上

暴力枚举a->b求解

#include<bits/stdc++.h>
using namespace std;
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
#define
typedef long long ll;
typedef unsigned long long ull;
ll mul(ll a,ll b){return (a*b)%F;}
ll add(ll a,ll b){return (a+b)%F;}
ll sub(ll a,ll b){return (a-b+llabs(a-b)/F*F+F)%F;}
void upd(ll &a,ll b){a=(a%F+b%F)%F;}
int read()
{
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) { x=x*10+ch-'0'; ch=getchar();}
return x*f;
}

#define
#define
int n,m;
int u[MAXM],v[MAXM],c[MAXM];
int Edge[MAXM],Next[MAXM],Pre[MAXM],Weight[MAXM],Siz=1;
void addedge(int u,int v,int c){
Edge[++Siz]=v;
Weight[Siz]=c;
Next[Siz]=Pre[u];
Pre[u]=Siz;
}
void addedge2(int u,int v,int c){addedge(u,v,c),addedge(v,u,c);}

bool vis[MAXN];
int d[MAXN][2];
int dep[MAXN]={0},path[MAXN]={0};
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;;
void spfa(int s,int op){
d[s][op]=0;
MEM(vis)
q.push(mp(0,s)); vis[s]=1; dep[s]=1;
while(!q.empty()) {
int now = q.top().se, d2 = q.top().fi;
q.pop();
if (d2!=d[now][op]) continue;

vis[now] = 0;
Forp(now) {
int v = Edge[p];
if (d[v][op]>d[now][op]+Weight[p]) {
d[v][op]=d[now][op]+Weight[p];
q.push(mp(d[v][op],v) );
vis[v]=1;
if (!op) {
path[v]=p;
}
}
}
}
}
int lis[MAXN],cnt=0,flag[MAXM]={0};
void pre() {
for(int u=n;u;flag[path[u]/2]=1,u=Edge[path[u]^1]) lis[++cnt]=u;
reverse(lis+1,lis+1+cnt);
For(i,cnt) dep[lis[i]]=i;
For(i,n) if (!dep[i]) {
int u;
for(u=i;!dep[u];u=Edge[path[u]^1]) ;
int d=dep[u];
u=i;
while(!dep[u]) dep[u]=d,u=Edge[path[u]^1];
}

}
int Ans[MAXN];
int minv[MAXN*4];
void build() {
MEMI(minv)

}
void modi(int L,int R,int l,int r,int o,int c) {
if (l<=L && R<=r) {
minv[o]=min(minv[o],c);
return;
}
int m=(L+R)>>1;
if (l<=m) modi(L,m,l,r,Lson,c);
if (m<r) modi(m+1,R,l,r,Rson,c);
}
void query(int L,int R,int o,int ans) {
ans=min(ans,minv[o]);
if (L==R) Ans[L]=ans;
else {
int m=(L+R)>>1;
query(L,m,Lson,ans);
query(m+1,R,Rson,ans);
}
}


void work(int u,int v,int c){
if (dep[u] == dep[v] ) return;
if (dep[u] > dep[v] ) swap(u,v);
modi(1,cnt-1,dep[u],dep[v]-1,1,d[u][0]+d[v][1]+c);
}

int main()
{
// freopen("bzoj4400.in","r",stdin);
// freopen(".out","w",stdout);

n = read(); m = read();
For(i,m) {
u[i]=read(); v[i] = read(); c[i] = read();
addedge2(u[i],v[i],c[i]);
}
MEMI(d)
spfa(1,0); spfa(n,1);
pre();
build();
For(i,m) if (!flag[i]) {
work(u[i],v[i],c[i]);
}
query(1,cnt-1,1,INF);
int ans1=Ans[1],ans2=0;
For(i,cnt-1) ans1=max(ans1,Ans[i]);
if (ans1!=d[n][0]) For(i,cnt-1) ans2+= (bool)(ans1 == Ans[i]);
else ans2=m;
printf("%d %d\n",ans1,ans2);
return 0;
}