AtCoder Beginner Contest 243 E - Edge Deletion( 删除冗余最短路)
传送门
给出一个个点条边的无向图,求在保证任意两点的最短路不变的情况下最多可以删除几条边。其中
解决这个问题关键在于一条结论:对于一条链接、长度的边,若存在除和之外的点满足则这条边删除之后对个点之间最短路没有影响。
因为这条边完全可以使用另外一组边代替并且更优(一段长的边明显不如很多个比较短的边)
于是用算出之后枚举边就能解决了。
一些结论:
利用这种方法求出剩余的边可能组成的不是一棵树,比如边长均为三的的完全图。
最短路树只是对于一个确定节点,和一个任意节点,树上两点的路径长度等于图中两点的最短路。所以的最短路树可以从为起点一遍求得。
代码:
#include<iostream>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
#define int long long
const int N=310;
const int INF=1e18;
int dis[N][N],u[N*N],v[N*N],w[N*N];
signed main(){
int n,m;
scanf("%lld%lld",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[i][j]=INF;
for(int i=1;i<=n;i++)dis[i][i]=0;
for(int i=1;i<=m;i++){
scanf("%lld%lld%lld",&u[i],&v[i],&w[i]);
dis[u[i]][v[i]]=dis[v[i]][u[i]]=min(dis[u[i]][v[i]],w[i]);
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
dis[j][i]=dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
int ans=0;
for(int i=1;i<=m;i++){
bool flag=0;
for(int j=1;j<=n;j++){
if(v[i]==j||u[i]==j)continue;
if(w[i]>=dis[u[i]][j]+dis[j][v[i]])flag=1;
}
if(flag)ans++;
}
printf("%lld",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2019-03-25 [ZJOI2015]地震后的幻想乡
2019-03-25 浅谈KMP算法