【NOI2007】 社交网络

题目描述
社交网络
问题描述
在社交网络(social network)的研究中,我们常常使用图论概念去解释一些
社会现象。
不妨看这样的一个问题。在一个社交圈子里有 n 个人,人与人之间有不同程
度的关系。我们将这个关系网络对应到一个 n 个结点的无向图上,两个不同的人
若互相认识,
则在他们对应的结点之间连接一条无向边,
并附上一个正数权值 c,
c 越小,表示两个人之间的关系越密切。
我们可以用对应结点之间的最短路长度来衡量两个人 s 和 t 之间的关系密切
程度,注意到最短路径上的其他结点为 s 和 t 的联系提供了某种便利,即这些结
点对于 s 和 t 之间的联系有一定的重要程度。我们可以通过统计经过一个结点 v
的最短路径的数目来衡量该结点在社交网络中的重要程度。
考虑到两个结点 A 和 B 之间可能会有多条最短路径。
我们修改重要程度的定
义如下:
令 Cs,t 表示从 s 到 t 的不同的最短路的数目, s,t(v)表示经过 v 从 s 到 t 的最短
C
路的数目;则定义
I (v ) =      C s , t (v )  
          ∑  -------------- s≠v,t ≠v
                 C s, t
为结点 v 在社交网络中的重要程度。
为了使 I(v)和 Cs,t(v)有意义,我们规定需要处理的社交网络都是连通的无向
图,即任意两个结点之间都有一条有限长度的最短路径。
现在给出这样一幅描述社交网络的加权无向图,请你求出每一个结点的重要
程度。
输入文件
输入文件中第一行有两个整数,n 和 m,表示社交网络中结点和无向边的数
目。在无向图中,我们将所有结点从 1 到 n 进行编号。
接下来 m 行,每行用三个整数 a, b, c 描述一条连接结点 a 和 b,权值为 c 的
无向边。注意任意两个结点之间最多有一条无向边相连,无向图中也不会出现自
环(即不存在一条无向边的两个端点是相同的结点)
。
输出文件
输出文件包括 n 行,每行一个实数,精确到小数点后 3 位。第 i 行的实数表
示结点 i 在社交网络中的重要程度。
输入样例
44
121
231
341
411
输出样例
1.000
1.000
1.000
1.000
样例说明
社交网络如下图所示。

对于 1 号结点而言,只有 2 号到 4 号结点和 4 号到 2 号结点的最短路经过 1
号结点,而 2 号结点和 4 号结点之间的最短路又有 2 条。因而根据定义,1 号结
点的重要程度计算为1     1         。由于图的对称性,其他三个结点的重
                                 -- + -- =1
                                 2     2
要程度也都是 1。
评分方法
本题没有部分分,仅当你的程序计算得出的各个结点的重要程度与标准输出
相差不超过0.001时,才能得到测试点的满分,否则不得分。
数据规模和约定
50%的数据中:n ≤ 10,m ≤ 45
100%的数据中:n ≤ 100,m ≤ 4 500,任意一条边的权值 c 是正整数,满
足:1 ≤ c ≤ 1 000。
所有数据中保证给出的无向图连通,且任意两个结点之间的最短路径数目不
超过 1010

 

 

题解

 

“2”了的算法:90分
 1 (*
 2     Problem:    NOI2007 社交网络
 3     Author:        chenyang
 4     Time:        2012.5.24 4:34 pm
 5     State:        90分
 6     Memo:        统计最短路条数
 7     Lesson:        在floyed的同时进行统计,不必dfs搜索 
 8 *)
 9 program network;
10 const maxn=105;
11 type
12   ty1=^ty2;
13   ty2=record
14     x:longint;
15     d:int64;
16     next:ty1;
17   end;
18 
19 var
20   n,m,i,j,k:longint;
21   d,sum:array[0..maxn,0..maxn] of int64;
22   first:array[0..maxn] of ty1;
23   v:array[0..maxn] of extended;
24 //=================
25 procedure insert(x,y:longint; d:int64);     inline;
26 var
27   p:ty1;
28 begin
29   new(p);
30   p^.x:=y;
31   p^.d:=d;
32   p^.next:=first[x];
33   first[x]:=p;
34 end;
35 //=================
36 procedure find(x,fa:int64);
37 var
38   i:longint;
39   p:ty1;
40 begin
41   inc(sum[fa,x]);
42   p:=first[x];
43   while p<>nil do
44   begin
45     if (p^.x<>fa)and(d[fa,p^.x]=d[fa,x]+p^.d) then find(p^.x,fa);
46     p:=p^.next;
47   end;
48 end;
49 //=================
50 begin
51   assign(input,'network.in'); reset(input);
52   assign(output,'network.out'); rewrite(output);
53   read(n,m);
54   fillchar(d,sizeof(d),$7);
55   for i:=1 to m do
56   begin
57     read(j,k);
58     read(d[j,k]); d[k,j]:=d[j,k];
59     insert(j,k,d[j,k]); insert(k,j,d[k,j]);
60   end;
61   for i:=1 to n do d[i,i]:=0;
62   for k:=1 to n do
63   for i:=1 to n do
64   if i<>k then
65   for j:=1 to n do
66   if (j<>i)and(j<>k)and(d[i,k]+d[k,j]<d[i,j]) then
67   d[i,j]:=d[i,k]+d[k,j];
68   for i:=1 to n do find(i,i);
69   for i:=1 to n do
70   for j:=1 to n do
71   if i<>j then
72   for k:=1 to n do
73   if (k<>i)and(k<>j)and(d[i,k]+d[k,j]=d[i,j]) then
74   v[k]:=v[k]+sum[i,k]*sum[k,j]/sum[i,j];
75   for i:=1 to n do writeln(v[i]:0:3);
76   close(input); close(output);
77 end.

 

floyed:100分
 1 (*
 2     Problem:    NOI2007 社交网络
 3     Author:        chenyang
 4     Time:        2012.5.24 4:41 pm
 5     State:        100分
 6     Memo:        统计最短路条数
 7 *)
 8 program network;
 9 const maxn=105;
10 var
11   n,m,i,j,k:longint;
12   d,sum:array[0..maxn,0..maxn] of int64;
13   v:array[0..maxn] of extended;
14 //=================
15 begin
16   assign(input,'network.in'); reset(input);
17   assign(output,'network.out'); rewrite(output);
18   read(n,m);
19   fillchar(d,sizeof(d),$7);
20   for i:=1 to m do
21   begin
22     read(j,k);
23     read(d[j,k]); d[k,j]:=d[j,k];
24     inc(sum[j,k]); inc(sum[k,j]);
25   end;
26   for i:=1 to n do d[i,i]:=0;
27   for k:=1 to n do
28   for i:=1 to n do
29   if i<>k then
30   for j:=1 to n do
31   if (j<>i)and(j<>k)and(d[i,k]+d[k,j]<d[i,j]) then
32   begin
33     d[i,j]:=d[i,k]+d[k,j];
34     sum[i,j]:=sum[i,k]*sum[k,j];
35   end else
36   if (j<>i)and(j<>k)and(d[i,k]+d[k,j]=d[i,j]) then
37   inc(sum[i,j],sum[i,k]*sum[k,j]);
38   for i:=1 to n do
39   for j:=1 to n do
40   if i<>j then
41   for k:=1 to n do
42   if (k<>i)and(k<>j)and(d[i,k]+d[k,j]=d[i,j]) then
43   v[k]:=v[k]+sum[i,k]*sum[k,j]/sum[i,j];
44   for i:=1 to n do writeln(v[i]:0:3);
45   close(input); close(output);
46 end.
posted @ 2012-05-29 21:34  datam  阅读(272)  评论(0编辑  收藏  举报