分析
我们高兴的发现数据范围特别小,所以我们可以随便搞。因为一共只砍掉一条路,所以我们先算出对于任意一个点如果将它的出边割掉一条则它到达终点的最坏情况的最短距离是多少,然后我们从终点向起点反着跑,按最短路思想算出答案即可,具体实现见代码。
代码
#include<bits/stdc++.h>
using namespace std;
#define sp cout<<"---------------------------------------------------"<<endl;
const int inf=0x3f3f3f3f;
class WarTransportation{
public:
int head[300000],nxt[300000],to[300000],w[300000],cnt;
int d2[300000],d[300000],vis[300000],bad[300000];
int head2[300000],nxt2[300000],to2[300000],w2[300000],cnt2;
priority_queue<pair<int,int> >q;
void add(int x,int y,int z){
nxt[++cnt]=head[x];
head[x]=cnt;
to[cnt]=y;
w[cnt]=z;
nxt2[++cnt2]=head2[y];
head2[y]=cnt2;
to2[cnt2]=x;
w2[cnt2]=z;
}
int ndij(int s,int N){
memset(vis,0,sizeof(vis));
memset(d,0x3f,sizeof(d));
d[s]=0;
q.push(make_pair(0,s));
while(!q.empty()){
int x=q.top().second;
q.pop();
if(vis[x])continue;
vis[x]=1;
for(int i=head[x];i;i=nxt[i])
if(i!=N||x!=s){
int y=to[i];
if(d[x]+w[i]<d[y]){
d[y]=d[x]+w[i];
q.push(make_pair(-d[y],y));
}
}
}
return d[2];
}
void getbad(int n){
int i,j;
memset(bad,0,sizeof(bad));
for(i=1;i<=n;i++)
if(i!=2)
for(j=head[i];j;j=nxt[j])
bad[i]=max(bad[i],ndij(i,j));
}
int getans(){
memset(vis,0,sizeof(vis));
memset(d2,0x3f,sizeof(d2));
d2[2]=0;
q.push(make_pair(0,2));
while(!q.empty()){
int x=q.top().second;
q.pop();
if(vis[x])continue;
vis[x]=1;
for(int i=head2[x];i;i=nxt2[i]){
int y=to2[i];
if(max(bad[y],d2[x]+w2[i])<d2[y]){
d2[y]=max(bad[y],d2[x]+w2[i]);
q.push(make_pair(-d2[y],y));
}
}
}
if(d2[1]>=inf)return -1;
return d2[1];
}
int messenger(int n,vector<string>highways){
int x,y,z;char ch;
stringstream buf(accumulate(highways.begin(),highways.end(),string()));
do{
buf>>x>>y>>z;
add(x,y,z);
}while(buf>>ch);
getbad(n);
return getans();
}
};