題意是若是把floyd算法的k循環寫在了最內層,有多少dis[i][j]仍是正確的。n是頂點數,m是單向邊數,n<=2000,m<=5000。c++
dis[i][j]是i到j的最短路長度,w[i][j]是i到j的邊權。算法
注意到m只有5000,圖不是很稠密,能夠作n次Dijkstra獲得dis數組,這部分複雜度是O(nmlogm)。數組
1.若是dis[i][j]==w[i][j],那麼按照題意中的算法仍然能獲得正確的結果。此時記can[i][j]=1。spa
2.若是存在x,使得can[i][x]==1&&can[x][j]==1&&x在i到j的任意一條最短路上,那麼can[i][j]=1。code
答案就是can[i][j]=1的有序組(i,j)數量。blog
直接這麼算can[i][j]複雜度過高,咱們注意到can[i][*]和can[*][j]的運算本質上是集合求交,能夠利用bitset維護。排序
同時,枚舉i,則i到j的全部最短路通過的點集pot[j]也能夠經過bitset維護,具體作法是每次枚舉一個i,就從新把頂點按照到i的最短路長度排序,從小到大計算pot[j]。若是dis[i][j]+w[j][k]==dis[i][k],則pot[k]|=pot[j](到k的最短路必定是由到k相鄰的點的最短路計算而來,因此這樣算出來的pot[k]不會遺漏)。it
這樣總複雜度應該是O(nmlogm+n2m/32),只能說勉強衝得過去,手寫bitset應該快一些,但我懶了。io
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e3+11; const int M=5e3+11; int n,m,top=-1,nowi; struct edge { int to; ll val; edge* nest; }e[M<<1],*v[N]; ll dis[N][N],w[N][N]; struct ob { int num; ll dist; }; bool operator <(const struct ob &p,const struct ob &q){return p.dist>q.dist;} priority_queue <ob> pq; void addedge(int from,int to,int val) { e[++top].to=to; e[top].val=val; e[top].nest=v[from]; v[from]=&e[top]; } bitset <N> f[N],g[N],pot[N]; int ord[N],ans; int cmp(int p,int q) { if(dis[nowi][p]==-1) return 0; else if (dis[nowi][q]==-1) return 1; else return dis[nowi][p]<dis[nowi][q]; } void Dijkstra(int now) { int i; struct ob cur; edge* ne; for(i=1;i<=n;i++) dis[now][i]=1e18; pq.push((ob){now,0}); while(!pq.empty()) { cur=pq.top(); pq.pop(); if(dis[now][cur.num]!=1e18) continue; dis[now][cur.num]=cur.dist; for(ne=v[cur.num];ne;ne=ne->nest)if(dis[now][ne->to]==1e18)pq.push((ob){ne->to,cur.dist+ne->val}); } } int main() { int i,j,k,from,to; ll val; edge* ne; scanf("%d%d",&n,&m); for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i!=j) w[i][j]=1e18; for(i=1;i<=m;i++) { scanf("%d%d%lld",&from,&to,&val); w[from][to]=val; addedge(from,to,val); } for(i=1;i<=n;i++) Dijkstra(i); for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(w[i][j]==dis[i][j]) f[i][j]=g[j][i]=1; for(i=1;i<=n;i++) { for(j=1;j<=n;j++) ord[j]=j; nowi=i; sort(ord+1,ord+n+1,cmp); for(j=1;j<=n;j++) pot[j].reset(),pot[j][j]=1; for(j=1;j<=n;j++)for(ne=v[ord[j]];ne;ne=ne->nest)if(dis[i][ord[j]]+ne->val==dis[i][ne->to]) pot[ne->to]|=pot[ord[j]]; for(j=1;j<=n;j++)if((f[i]&g[j]&pot[j]).count())f[i][j]=g[j][i]=1; } for(i=1;i<=n;i++) ans+=f[i].count(); printf("%d\n",ans); return 0; }