2.重要程度
Description
为了正确开导lyh,也为了警示后人,指导老师进行了严肃而又激情的讲说。
人的一生会遇到 个特殊事件(比如:初赛没过和谈恋爱)。事件之间肯定是有联系的,而且是双向的(参考上述 例子)。简单的说, 个事件构成了一个有 条边的无向联通图。
直接讲述重要性可能会使某些人难以接受(继续参考上述例子)。为了比较科学一点,我们设 为事件 的重要 程度,有 I(x)=∑C(s,t,x)/C(s,t)
其中,C(s,t) 表示s 到t 的最短路径的数目,而 C(s,t,x)表示s 到t 的最短路径中经过 x的路径数目。因为是无向连通 图,所以一定存在至少一条最短路径,即每个事件的重要程度一定有意义。
由于计算量较大,为了避免尴尬,你要及时说出所有事件的重要程度。
Input
输入文件为
第一行两个整数 和 ,表示总事件数和事件构成连通图的边数,事件按 到 编号。
接下来 行,每行三个整数 , 和 。表示一条连接 , ,权值为 的无向边。
Output
输出文件为
输出共 行,每行一个实数,精确到小数点后三位。第 行表示 。
Sample Input
4 4 1 2 1
2 3 1 3 4 1 4 1 1 Sample Output
1.000
1.000 1.000 1.000
对于1号结点而言,只有2号到4号结点和4号到2号结点的最短路经过1号结点,而2号结点和4号结点之间的最短路 又有2条。因而根据定义,1号结点的重要程度计算为1/2+1/2=1。由于图的对称性,其他三个结点的重要程度也都 是1。
Data Constraint
对于50%数据,n<=10 , 对于100%数据, n<=100,
分析:spfa求出每对点之间的最短路径数量G[i][j],那么C(i,j,x)=G[i][x]*G[x][j]。
代码
#include <cstdio>
#include <queue>
#define N 105
#define ll long long
#define inf 1e15
using namespace std;
struct arr
{
int to,nxt;
ll w;
}a[N * N];
ll f[N][N],g[N][N][N],G[N][N];
int n,m,l,ls[N * N];
bool vis[N];
queue<int> q;
void spfa(int s)
{
for (int i = 1; i <= n; i++)
{
vis[i] = false;
f[s][i] = inf;
}
while (q.size()) q.pop();
f[s][s] = 0;
G[s][s] = 1;
q.push(s);
while (q.size())
{
int u = q.front();
q.pop();
vis[u] = false;
for (int i = ls[u]; i; i = a[i].nxt)
{
int v = a[i].to;
if (f[s][u] + a[i].w < f[s][v])
{
f[s][v] = f[s][u] + a[i].w;
G[s][v] = G[s][u];
if (!vis[v])
{
vis[v] = true;
q.push(v);
}
}
else if (f[s][u] + a[i].w == f[s][v])
G[s][v] += G[s][u];
}
}
}
void add(int x, int y, ll w)
{
a[++l].to = y;
a[l].w = w;
a[l].nxt = ls[x];
ls[x] = l;
}
int main()
{
freopen("importance.in","r",stdin);
freopen("importance.out","w",stdout);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++) f[i][j] = inf;
for (int i = 1; i <= m; i++)
{
int x, y;
ll w;
scanf("%d%d%lld", &x, &y, &w);
add(x, y, w);
add(y, x, w);
}
for (int i = 1; i <= n; i++) spfa(i);
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (i != j && j != k && i != k)
if (f[i][k] + f[k][j] == f[i][j])
g[i][j][k]= G[i][k] * G[k][j];
for (int k = 1; k <= n; k++)
{
double ans = 0;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (i != j && i != k && j != k)
ans += ((1.0 * g[i][j][k]) / (1.0 * G[i][j]));
printf("%.3lf\n", ans);
}
fclose(stdin);
fclose(stdout);
}