您的位置:首页 > 大数据 > 人工智能

ICPCCamp2016day 1 - All Pair Shortest Path【bitset优化】

2016-04-13 23:01 609 查看
题意:给你一个n*n的01矩阵,代表一个有向图i到j是否连边,求所有i到j的最短路的平方和。

分析:由于边的长度的都为1,我们考虑bfs每次n^2可以求出i到其他点的最短路径,n^3求出答案,但是时间复杂度承受不了。

我们可以发现bfs时遍历了一个点后,其他的点都不用遍历它,我们可以用一个二进制数存下当前还没有遍历的点,bfs的时候我们只需要遍历当前点i要遍历的点&剩下的点。

时间复杂度n^3/64,这里要手写bitset实现。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 2005
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int read() {
char c;
int ans=0,f=1;c=getchar();
while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9') {ans=ans*10+c-'0';c=getchar();}
return  ans*f;
}
int n;
ll e[Mn][Mn/61+1];
ll lowbit(ll x) {
return x&(-x);
}
queue<int> q;
int dis[Mn][Mn];
ll bit[Mn/61+1];
void bfs(int st) {
while(!q.empty()) q.pop();
q.push(st);
for(int i=0;i<=n/61;i++) bit[i]=(1LL<<61)-1;
bit[(st-1)/61]-=(1LL<<(st-(st-1)/61*61-1));
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=0;i<=n/61;i++) {
ll x=e[u][i]&bit[i];
while(x>0) {
ll y=lowbit(x);
int v=(int)log2(y)+1+i*61;
dis[st][v]=dis[st][u]+1;
q.push(v);
bit[i]-=y;
x-=y;
}
}
}
}
int main() {
n=read();
char s[Mn];
for(int i=1;i<=n;i++) {
scanf("%s",s);
for(int j=1;j<=n;j++) {
if(s[j-1]-'0'==1) {
int k=(j-1)/61;
e[i][k]|=(1LL<<(j-k*61-1));
}
}
}
ll sum=0;
for(int i=1;i<=n;i++) {
bfs(i);
for(int j=1;j<=n;j++) {
if(i==j) continue;
if(dis[i][j]==0) dis[i][j]=n;
sum+=dis[i][j]*dis[i][j];
}
}
printf("%lld\n",sum);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: