BZOJ 1491 [NOI2007]社交網絡 - Floyd(相關的DP思想)

首先關於Floyd的理解,有一篇博客講的很詳細:
http://www.cnblogs.com/chenying99/p/3932877.html

Floyd從本質上來講是一種DP+滾動數組優化,省去了一維k,即對於已用幾條邊的討論,而在這道題中,所求的是兩點之間經過k點的最短路徑條數,那麼在dp時加上用乘法原理實現的路徑條數統計即可。最後經過k點的條數統計一下即可。

這道題還要注意一個問題,最後統計條數之時,由於是一條路徑,不存在自環的問題,所以i、j、k三者不能相等。
而且還有一個問題,這道題路徑條數統計會爆int,乾脆用double好了。

#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>

using namespace std;

const int maxn=105;

int n,m;
int dist[maxn][maxn];
double deno[maxn][maxn];
double res[maxn];

void Floyd()
{
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(dist[i][j]>dist[i][k]+dist[k][j])
                {
                    dist[i][j]=dist[i][k]+dist[k][j];
                    deno[i][j]=deno[i][k]*deno[k][j];
                }
                else if(dist[i][j]==dist[i][k]+dist[k][j])
                    deno[i][j]+=deno[i][k]*deno[k][j];
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j&&i!=k&&j!=k)
                    if(dist[i][k]+dist[k][j]==dist[i][j]&&deno[i][j])
                        res[k]+=(deno[i][k]*deno[k][j])/deno[i][j];
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(dist,127/3,sizeof dist);
    for(int i=1,u,v,val;i<=m;i++)
    {
        scanf("%d%d%d",&u,&v,&val);
        dist[u][v]=dist[v][u]=val;
        deno[u][v]=deno[v][u]=1;
    }
    Floyd();
    for(int i=1;i<=n;i++)
        printf("%.3lf\n",res[i]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章