题解 P2047 【[NOI2007]社交网络】
xzyxzy
2018-05-28 09:43:51
## 来一个SPFA的题解
## 先上代码
```
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define ll long long
using namespace std;
int read()
{
char ch=getchar();int h=0,t=1;
while((ch>'9'||ch<'0')&&ch!='-') ch=getchar();
if(ch=='-') t=-1,ch=getchar();
while(ch>='0'&&ch<='9') h=h*10+ch-'0',ch=getchar();
return h*t;
}
int N,M,g[110][110],head[110],cnt;
int dis[110],vis[110];
ll w[110][110],fr[110][110][110];
queue<int>Q;
struct edge{int next,to,w;}a[10010];
void link(int x,int y,int w){a[++cnt]=(edge){head[x],y,w};head[x]=cnt;}
void SPFA(int f)
{
memset(dis,63,sizeof(dis));
Q.push(f);vis[f]=1;dis[f]=0;w[f][f]=1;
while(!Q.empty())
{
int x=Q.front();
for(int i=head[x];i;i=a[i].next)
{
int R=a[i].to;
if(dis[R]<dis[x]+a[i].w) continue;
if(dis[R]==dis[x]+a[i].w)
{
w[f][R]=w[f][R]-fr[f][R][x]+w[f][x];
fr[f][R][x]=w[f][x];
}
else
{
dis[R]=dis[x]+a[i].w;
w[f][R]=w[f][x];
for(int p=1;p<=N;p++) fr[f][R][p]=0;
fr[f][R][x]=w[f][x];
}
if(!vis[R]) vis[R]=1,Q.push(R);
}
Q.pop();vis[x]=0;
}
for(int i=1;i<=N;i++) g[f][i]=dis[i];
}
int main()
{
N=read();M=read();
for(int i=1;i<=M;i++)
{
int x=read(),y=read(),w=read();
link(x,y,w);link(y,x,w);
}
for(int i=1;i<=N;i++) SPFA(i);
for(int k=1;k<=N;k++)
{
double ans=0;
for(int x=1;x<=N;x++)
for(int y=1;y<=N;y++)
if(x!=k&&k!=y&&g[x][y]==g[x][k]+g[k][y])
ans+=1.0*w[x][k]*w[k][y]/w[x][y];
printf("%.3lf\n",ans);
}
return 0;
}
```
这题由于ans+=w[x][k]*w[k][y]/x[x][y],没有乘w[k][y]而调试半个小时,甚至还尝试了Floyd的做法
意思就是x->y,那么w(ay)[y]+=w(ay)[x],但是x被松弛后不能直接加,就要用fr来记录x对y的路径条数的贡献
Floyd相对好写些,这里只提供一个SPFA的思路,Floyd可以看楼下的,写的很棒