最短路计数
前置知识
- 最短路的一个很好的性质:从
到 的最短路上的一个节点 ,都满足 到 的路径是关于 单源最短路的最短路
证明:
反证法,假设
故得证。
- 在
到 的最短路径上一定不存在环
证明:
考虑反证法,因为这个图的边权非负,所以环的权值为非负数,所以一定不会比不经过这个环更优。
故得证。
注: 上述结论是在图的边权非负时才成立的,如果图的边权为负数上述结论就不一定成立了。
例题[HAOI2012] 道路
直接队每一条边进行枚举肯定会
设
很显然,对于一条边
代码如下:
#include<bits/stdc++.h>
using namespace std;
const int N=1550,M=5050;
const int mod=1e9+7;
int n,m,head[N],cnt,to[M],nxt[M],w[M],dis[N],fro[M],in[N],cnt1[N],cnt2[N],s[N],ans[M];
bool vis[N],mark[M];
void add(int u,int v,int f)
{
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
w[cnt]=f;
fro[cnt]=u;
}
struct node{
int val,pos;
bool operator >(const node &x)const{
return val>x.val;
}
};
void dij(int s)
{
priority_queue<node,vector<node>,greater<node> >q;
memset(dis,0x3f,sizeof(dis));
memset(vis,0,sizeof(vis));
memset(mark,0,sizeof(mark));
dis[s]=0;
q.push(node{dis[s],s});
while(!q.empty())
{
node t=q.top();q.pop();
if(vis[t.pos])continue;
vis[t.pos]=1;
for(int i=head[t.pos];i;i=nxt[i])
{
int v=to[i];
if(dis[v]>dis[t.pos]+w[i])
{
dis[v]=dis[t.pos]+w[i];
q.push(node{dis[v],v});
}
}
}
for(int i=1;i<=m;i++)
if(dis[to[i]]==dis[fro[i]]+w[i])mark[i]=true;
return;
}
void topo(int fs)
{
memset(cnt1,0,sizeof(cnt1));
memset(cnt2,0,sizeof(cnt2));
memset(in,0,sizeof(in));
queue<int>q;
for(int i=1;i<=m;i++)
{
if(mark[i]==false)continue;
in[to[i]]++;
}
q.push(fs);
cnt1[fs]=1;
int tag=0;
while(!q.empty())
{
int x=q.front();q.pop();
s[++tag]=x;
for(int i=head[x];i;i=nxt[i])
{
if(mark[i]==false)continue;
in[to[i]]--;
if(in[to[i]]==0)q.push(to[i]);
cnt1[to[i]]+=cnt1[x];
cnt1[to[i]]%=mod;
}
}
for(int i=tag;i;i--)
{
int x=s[i];
cnt2[x]++;
for(int j=head[x];j;j=nxt[j])
{
if(mark[j]==false)continue;
cnt2[x]+=cnt2[to[j]];
cnt2[x]%=mod;
}
}
}
int main()
{
scanf("%d %d",&n,&m);
for(int i=1,u,v,w;i<=m;i++)
{
scanf("%d %d %d",&u,&v,&w);
add(u,v,w);
}
for(int i=1;i<=n;i++)
{
dij(i);topo(i);
for(int i=1;i<=m;i++)
{
// cout<<cnt1[fro[i]]<<" "<<cnt2[to[i]]<<endl;
if(mark[i])
{
ans[i]+=(cnt1[fro[i]]%mod*cnt2[to[i]]%mod)%mod;
ans[i]%=mod;
}
}
}
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}
时间复杂度
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现