【JZOJ3808】道路值守

Description

Crossbell 自治州有着四通八达的现代化交通。时值独立庆典之际,随着来自周边国家旅客的日益增多,犯罪行为也悄无声息开始滋长起来。
特别任务支援科的警察们从总部收到了关于调查伪装在游客中的犯罪分子的请求。通过调查,他们得到了一张地图,记载了Crossbell 自治州内每一条道路的长度。
显然,为了减少犯罪行为被发现的可能性,犯罪分子总是会选择最短的路径来行动。为了方便安排人手和推测犯罪分子采取的路线,他们希望得知任意两个地点之间,有多少条犯罪分子可能会选择的道路。

Solution

点很少,先跑一次floyd。

枚举一个起点 s 和终点t,然后枚举终点所连向的边,得出在起点终点之间最短路的边数为 dt

然后再枚举起点和终点,枚举一个中间点 k ,看看该点是否在起点和终点的最短路上,然后两点的答案加上dk

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define N 510
using namespace std;
int f[N][N],a[N][N];
int sum[N],s[N][N];
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    memset(f,60,sizeof(f));
    memset(a,60,sizeof(a));
    fo(i,1,m)
    {
        int u,v,w;
        scanf("%d %d %d",&u,&v,&w);
        a[u][v]=a[v][u]=w;
        f[u][v]=f[v][u]=w;
    }
    fo(i,1,n) f[i][i]=0,a[i][i]=0;
    fo(k,1,n)
    fo(i,1,n)
    fo(j,1,n)
    if(f[i][j]>f[i][k]+f[k][j]) f[i][j]=f[i][k]+f[k][j];
    fo(i,1,n-1)
    {
        memset(sum,0,sizeof(sum));
        fo(j,1,n) if(i!=j)
        fo(k,1,n) if(j!=k)
        if(f[i][k]+a[k][j]==f[i][j]) sum[j]++;
        fo(j,i+1,n)
        fo(k,1,n)
        if(f[i][k]+f[k][j]==f[i][j] && f[i][j]<=10000000) s[i][j]+=sum[k];
    }
    fo(i,1,n-1)
    fo(j,i+1,n) printf("%d ",s[i][j]);
}
posted @ 2017-01-09 19:14  sadstone  阅读(43)  评论(0编辑  收藏  举报