A
B
C
D
E
F
G
H水题
I水题
J考察floyd算法的理解
K
J
题意: floyd算法写法为
for k from 1 to n
for i from 1 to n
for j from 1 to n
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j])
现在粗心不小心写成了
for i from 1 to n
for j from 1 to n
for k from 1 to n
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j])
现在给出n个点m条边的有向图,问这么算有多少个dis[u][v]是正确的
解析:这个错误的版本本质就是枚举每个点更新其它点,只有当存在k,i->k直接相连且就是i与k的最短路,j->k直接相连且就是j与k的最短路。那么i->j的最短路就可以正确算出来(或者i->j直接相连且就是i与j的最短路)。然后就考虑跑dijkstra了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll inf=1e15;
priority_queue<pair<ll,ll>,vector<pair<ll,ll>>,greater<pair<ll,ll>>> q;
ll n, m, ans;
ll g[2050][2050];
ll dis[2050][2050];
vector<pair<ll,ll>> e[2050];
void dijkstra(ll p)
{
for(ll i=1;i<=n;i++)
dis[p][i]=inf;
dis[p][p]=0;
for(ll i=0;i<e[p].size();i++)
q.push(e[p][i]);
while(q.size())
{
pair<ll,ll> t=q.top();
q.pop();
ll u=t.second;
if(dis[p][u]!=inf)
continue;
dis[p][u]=t.first;
for(ll i=0;i<e[u].size();i++)
{
ll v=e[u][i].second;
if(dis[p][v]!=inf)
continue;
pair<ll,ll> kk;
kk.first=e[u][i].first+dis[p][u];
kk.second=v;
q.push(kk);
}
}
e[p].clear();
for(ll i=1;i<=n;i++)
{
if (dis[p][i]==g[p][i]&&dis[p][i]<inf&&p!=i)
{
pair<ll,ll> kk;
kk.first=dis[p][i];
kk.second=i;
e[p].push_back(kk);
}
}
}
void solve(ll p)
{
pair<ll,ll> k;
for(ll i=0;i<e[p].size();i++)
{
k.first=0;
k.second=e[p][i].second;
q.push(k);
}
while(q.size())
{
pair<ll,ll> t=q.top();
q.pop();
ll id=t.first;
ll u=t.second;
for(ll i=0;i<e[u].size();i++)
{
ll v=e[u][i].second;
ll w=e[u][i].first;
if(v<id)
continue;
if(dis[p][v]==g[p][v]||dis[p][v]>=inf)
continue;
if(dis[p][v]==dis[p][u]+w)
{
pair<ll,ll> kk;
kk.first=v;
kk.second=v;
q.push(kk);
kk.first=dis[p][v];
kk.second=v;
e[p].push_back(kk);
g[p][v]=dis[p][v];
}
}
}
}
int main()
{
scanf("%lld%lld",&n,&m);
for(ll i=0;i<2050;i++)
for(ll j=0;j<2050;j++)
g[i][j]=inf;
for(ll i=1;i<=m;i++)
{
ll u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
pair<ll,ll> x;
x.first=w;
x.second=v;
e[u].push_back(x);
g[u][v]=w;
}
for(ll i=1;i<=n;i++)
g[i][i]=0;
for(ll i=1;i<=n;i++)
dijkstra(i);
for(ll i=1;i<=n;i++)
solve(i);
ans=0;
for(ll i=1;i<=n;i++)
for(ll j=1;j<=n;j++)
if(g[i][j]==dis[i][j]||g[i][j]>=inf&&dis[i][j]>=inf)
ans++;
printf("%lld\n",ans);
}