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

来源:互联网 发布:淘宝嘉年华是什么意思 编辑:程序博客网 时间:2024/06/04 00:19

题意:给你一个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)|1using 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;}


0 0
原创粉丝点击