题目大意:原题链接
解题思路:此题要求多点最短距离,但是直接套用floyd会超时.
然后我们想直接从每一个点开始bfs就好了,但是还是会TLE,为什么呢?
因为你访问了很多次没有意义的地方,因为有些点你曾经访问过,但是在你遍历边集的时候,你还去访问他,这个行为就会很多余。
所以我们用set来优化一下.
这个均摊下来,复杂度大概是n^2*logn的
最蛋疼的情况是你每次最多更新sqrt(n)个点,你需要更新sqrt(n)次,每次遍历和更新的复杂度都是logn,大概是这样……
erase(key) 删除键值key的值
erase(iterator) 删除定位器iterator指向的值
erase(first,second) 删除定位器first和second之间(左闭右开)的值
注意:
1.set中的数据是自动去重的;
2.it指向set的某个数,如果set这个数被erase,it的指针会变;
#include<set> #include<queue> #include<string> #include<iostream> using namespace std; set<int> S; int n,d[2010]; string g[2010]; queue<int> que; long long ans=0; void Spfa(int x) { S.clear(); while(!que.empty()) que.pop(); for(int i=0;i<n;i++) d[i]=n; for(int i=0;i<n;i++){ if(i!=x) S.insert(i); } d[x]=0,que.push(x); while(!que.empty()){ int u=que.front(); que.pop(); set<int>::iterator it=S.begin();//每次必须重新定义,因为set集合S每次都在变化 while(S.size()&&it!=S.end()){ int v=*it; if(g[u][v]=='1'){ d[v]=d[u]+1; it++;//it++位置很重要 que.push(v); S.erase(v); } else it++; } } for(int i=0;i<n;i++) ans+=d[i]*d[i]; } int main() { cin>>n; for(int i=0;i<n;i++) cin>>g[i]; for(int i=0;i<n;i++) Spfa(i); cout<<ans<<endl; }