题目要求删除图上的一条边,使得最短路最长,也可以删边后不可达。
先跑一遍最短路,求出不删边时最短路上的所有边。然后枚举删除这些边,再次迪杰斯特拉,每次更新最大值。
作为一个菜鸡,这题一A了,然后没出息的笑了笑。
上代码
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int maxn = 1005;
const int inf = 1<<20;
int n,m;
struct node{
int to;
int next;
int w;
int vis;
node(){
}
node(int a,int b,int c):to(a),next(b),w(c){
vis = 0;
}
}edge[50002<<1];
int head[maxn];
int tot;
void add_edge(int u,int v,int w)
{
edge[tot] = node(v,head[u],w);
head[u] = tot++;
edge[tot] = node(u,head[v],w);
head[v] = tot++;
}
int dist[maxn];
struct Edge{
int id;
int dist;
Edge(int a,int b):id(a),dist(b){
}
bool operator < (const Edge& T)const{
return dist>T.dist;
}
};
int par[maxn];
int cost[maxn];
vector<int>G[maxn];
void dij()
{
for(int i=1;i<=n;i++){
par[i] = i;
dist[i] = inf;
}
priority_queue<Edge>que;
dist[1] = 0;
que.push(Edge(1,0));
while(!que.empty())
{
Edge edg = que.top(); que.pop();
if(dist[edg.id]<edg.dist) continue;
for(int i=head[edg.id];i!=-1;i=edge[i].next)
{
if(edge[i].vis==2) continue;
int v = edge[i].to;
int w = edge[i].w;
if(dist[v]>dist[edg.id]+w)
{
dist[v] = dist[edg.id]+w;
par[v] = edg.id;
cost[v] = w;
que.push(Edge(v,dist[v]));
}
}
}
}
int main()
{
int cases;
scanf("%d",&cases);
while(cases--)
{
int u,v,w;
scanf("%d%d",&n,&m);
tot = 0;
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
}
for(int i=1;i<=n;i++)
G[i].clear();
dij();
if(dist[n]==inf)
{
printf("-1\n");
continue;
}
int k = n;
while(k!=par[k])
{
// printf("%d\n",k);
G[par[k]].push_back(k);
k = par[k];
}
int ma = -1;
for(int i=1;i<=n;i++)
{
if((int)G[i].size()==0)
continue;
int x = i;
int y = G[i][0];
int cc = cost[y];
int temp;
for(int j=head[x];j!=-1;j=edge[j].next)
{
int to = edge[j].to;
int w = edge[j].w;
if(to==y&&w==cc)
{
edge[j].vis = 2;
temp = j;
// printf("%d\n",j);
break;
}
}
dij();
// printf("%d\n",dist[n]);
edge[temp].vis = 0;
ma = max(ma,dist[n]);
}
if(ma==inf)
printf("-1\n");
else
printf("%d\n",ma);
}
return 0;
}