题意:
删除1—N最短路上的一条边,使图剩下部分1—N的最短路最长
关于多条最短路:
这道题目的思路还是很容易想到的,我们直接找最短路,然后枚举删除最短路上的边,然后找出结果就行了。但值得一提的是,开始自己考虑了有多条最短路的问题,然后我就将所有最短路上的边都进行标记,然后就MLE了,感觉出题不严谨。其实不是,就算有多条最短路,我们只需要其中一条就行了。
多条最短路有两种情况
- 最短路没有重合边:这个时候我们删除任意其中一条最短路上的边,求出的最短路还是不变的。
- 两条最短路有重合边,这个时候我们只要删除一条重合边,就能让图不连通。
- 多条最短路头重合边,可以分别转化成1、2的情况
只找出一条最短路就可以,AC代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define res register int
const int maxn=1005;
int N,M;
int dis[maxn][maxn];
int pre[maxn];
int dij1()
{
int len[maxn],vis[maxn];
memset(vis,0,sizeof(vis));
memset(len,inf,sizeof(len));
len[1]=0;
for(res i=2;i<=N;i++){
len[i]=dis[1][i];
if(inf!=dis[1][i]) pre[i]=1;
}
vis[1]=1;
for(res i=1;i<=N-1;i++){
int minc=inf,p=-1;
for(res j=1;j<=N;j++){
if(!vis[j]&&len[j]<minc){
minc=len[j];
p=j;
}
}
if(inf==minc) break;
vis[p]=1;
for(res j=1;j<=N;j++){
if(!vis[j]&&len[j]>len[p]+dis[p][j]){
len[j]=len[p]+dis[p][j];
pre[j]=p;
}
}
}
if(inf==len[N]) return -1;
else return len[N];
}
int dij2()
{
int len[maxn],vis[maxn];
memset(vis,0,sizeof(vis));
memset(len,inf,sizeof(len));
len[1]=0;
for(res i=2;i<=N;i++){
len[i]=dis[1][i];
}
vis[1]=1;
for(res i=1;i<=N-1;i++){
int minc=inf,p=-1;
for(res j=1;j<=N;j++){
if(!vis[j]&&len[j]<minc){
minc=len[j];
p=j;
}
}
if(inf==minc) break;
vis[p]=1;
for(res j=1;j<=N;j++){
if(!vis[j]&&len[j]>len[p]+dis[p][j])
len[j]=len[p]+dis[p][j];
}
}
if(inf==len[N]) return -1;
else return len[N];
}
int main()
{
while(EOF!=scanf("%d%d",&N,&M))
{
//init
for(res i=0;i<=N;i++){
for(res j=0;j<=N;j++){
dis[i][j]=inf;
}
dis[i][i]=0;
pre[i]=-1;
}
int from,to,val;
for(res i=0;i<M;i++){
scanf("%d%d%d",&from,&to,&val);
dis[from][to]=dis[to][from]=val;
}
int ans=dij1();
if(-1==ans){
printf("-1\n");
continue;
}
//开始枚举每一条边
// for(res i=1;i<=N;i++){
// printf("%d:",i);
// for(res j=0;j<pre[i].size();j++){
// printf("%d ",pre[i][j]);
// }
// printf("\n");
// }
ans=-inf;
int flag=0;
int t=N;
while(-1!=pre[t]){
int to=t,from=pre[t];
int temp1=dis[from][to],temp2;
dis[from][to]=dis[to][from]=inf;
temp2=dij2();
if(-1==temp2){
ans=-1;
flag=1;
break;
}
ans=max(ans,temp2);
dis[from][to]=dis[to][from]=temp1;
t=pre[t];
}
printf("%d\n",ans);
}
}
记录所有最短路上的边就MLE
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define res register int
const int maxn=1005;
int N,M;
int dis[maxn][maxn];
vector<int> pre[maxn];
vector<int> e[maxn];
int dij1()
{
int len[maxn],vis[maxn];
memset(vis,0,sizeof(vis));
memset(len,inf,sizeof(len));
len[1]=0;
for(res i=2;i<=N;i++){
len[i]=dis[1][i];
if(inf!=dis[1][i]) pre[i].push_back(1);
}
vis[1]=1;
for(res i=1;i<=N-1;i++){
int minc=inf,p=-1;
for(res j=1;j<=N;j++){
if(!vis[j]&&len[j]<minc){
minc=len[j];
p=j;
}
}
if(inf==minc) break;
vis[p]=1;
for(res j=1;j<=N;j++){
if(!vis[j]&&len[j]>len[p]+dis[p][j]){
len[j]=len[p]+dis[p][j];
pre[j].clear();
pre[j].push_back(p);
// e[p].clear();
// e[p].push_back((edge){j,dis[p][j]});
}else if(!vis[j]&&len[j]==len[p]+dis[p][i]){
pre[j].push_back(p);
// e[p].push_back((edge){j,dis[p][j]});
}
}
}
if(inf==len[N]) return -1;
else return len[N];
}
int dij2()
{
int len[maxn],vis[maxn];
memset(vis,0,sizeof(vis));
memset(len,inf,sizeof(len));
len[1]=0;
for(res i=2;i<=N;i++){
len[i]=dis[1][i];
}
vis[1]=1;
for(res i=1;i<=N-1;i++){
int minc=inf,p=-1;
for(res j=1;j<=N;j++){
if(!vis[j]&&len[j]<minc){
minc=len[j];
p=j;
}
}
if(inf==minc) break;
vis[p]=1;
for(res j=1;j<=N;j++){
if(!vis[j]&&len[j]>len[p]+dis[p][j])
len[j]=len[p]+dis[p][j];
}
}
if(inf==len[N]) return -1;
else return len[N];
}
void dfs(int n)
{
if(1==n) return;
int fa;
for(res i=0;i<pre[n].size();i++){
fa=pre[n][i];
dfs(fa);
e[fa].push_back(n);
}
}
int main()
{
while(EOF!=scanf("%d%d",&N,&M))
{
//init
for(res i=0;i<=N;i++){
e[i].clear();
for(res j=0;j<=N;j++){
dis[i][j]=inf;
}
dis[i][i]=0;
}
int from,to,val;
for(res i=0;i<M;i++){
scanf("%d%d%d",&from,&to,&val);
dis[from][to]=dis[to][from]=val;
}
int ans=dij1();
if(-1==ans){
printf("-1\n");
continue;
}
dfs(N);
//开始枚举每一条边
// for(res i=1;i<=N;i++){
// printf("%d:",i);
// for(res j=0;j<pre[i].size();j++){
// printf("%d ",pre[i][j]);
// }
// printf("\n");
// }
ans=-inf;
int flag=0;
for(res i=1;i<=N;i++){
for(res j=0;j<e[i].size();j++){
int to=e[i][j];
int temp1=dis[i][to],temp2;
dis[i][to]=dis[to][i]=inf;
temp2=dij2();
if(-1==temp2){
ans=-1;
flag=1;
break;
}
ans=max(ans,temp2);
dis[i][to]=dis[to][i]=temp1;
}
if(flag) break;
}
printf("%d\n",ans);
}
}