Luogu2164 SHOI2007 交通网络 期望、BFS、拓扑排序

传送门


题目还算不难吧

首先我们枚举点$i$,将其他所有点到这个点的最短路求出来

然后我们在这一次建出的最短路$DAG$的反图上进行拓扑排序。假设我们算到了点$j$,点$j$的人流量为$t_j$,点$j$连出去的边到达的点为点集$\{v\}$,那么对于每一个点$u \in \{v\}$,边$(j,u)$的流量就会增加$\frac{t_j}{|\{v\}|}$,$t_u$会加上$\frac{t_j}{|\{v\}|}$

总时间复杂度$O(N^2)$

 1 #include<bits/stdc++.h>
 2 #define ld long double
 3 using namespace std;
 4 inline int read(){
 5     int a = 0;
 6     char c = getchar();
 7     while(!isdigit(c))    c = getchar();
 8     while(isdigit(c))    a = (a << 3) + (a << 1) + (c ^ '0') , c = getchar();
 9     return a;
10 }
11 inline int max(int a , int b){
12     return a > b ? a : b;
13 }
14 struct Ed{
15     int start , end , upEd;
16 }ans[100001];
17 bool vis[301] , ifRail[301][301];
18 long long Times[301];
19 int firEd[301] , minRoute[301];
20 ld peo[301][301] , To[301][301];
21 struct cmp{
22     bool operator() (const int& a, const int& b ){
23         return minRoute[a] < minRoute[b];
24     }
25 };
26 int main(){
27     int N = read() , M = read();
28     for(int i = 1 ; i <= M ; i++){
29         int a = read() , b = read();
30         ans[(i << 1) - 1].start = a;
31         ans[(i << 1) - 1].end = b;
32         ans[(i << 1) - 1].upEd = firEd[a];
33         firEd[a] = (i << 1) - 1;
34         ans[i << 1].start = b;
35         ans[i << 1].end = a;
36         ans[i << 1].upEd = firEd[b];
37         firEd[b] = i << 1;
38         ifRail[a][b] = ifRail[b][a] = 1;
39     }
40     for(int i = 1 ; i <= N ; i++)
41         for(int j = 1 ; j <= N ; j++)    To[i][j] = read();
42     for(int i = 1 ; i <= N ; i++){
43         memset(minRoute , 0x3f , sizeof(minRoute));
44         memset(Times , 0 , sizeof(Times));
45         minRoute[i] = 0;
46         Times[i] = 1;
47         queue < int > q;
48         priority_queue < int , vector < int > , cmp > q1;
49         q.push(i);
50         while(!q.empty()){
51             int t = q.front();
52             q.pop();
53             bool f = 0;
54             for(int j = firEd[t] ; j ; j = ans[j].upEd)
55                 if(minRoute[ans[j].end] > minRoute[t] + 1){
56                     minRoute[ans[j].end] = minRoute[t] + 1;
57                     Times[ans[j].end] = Times[t];
58                     q.push(ans[j].end);
59                     f = 1;
60                 }
61                 else    if(minRoute[ans[j].end] == minRoute[t] + 1){
62                     Times[ans[j].end] += Times[t];
63                     f = 1;
64                 }
65             if(!f)    q1.push(t);
66         }
67         memset(vis , 0 , sizeof(vis));
68         vis[i] = 1;
69         while(!q1.empty()){
70             int t = q1.top();
71             q1.pop();
72             for(int j = 1 ; j <= N ; j++)
73                 if(ifRail[j][t] && minRoute[j] == minRoute[t] - 1){
74                     ld t1 = (ld)To[i][t] * Times[j] / Times[t];
75                     peo[j][t] += t1;
76                     peo[t][j] += t1;
77                     To[i][j] += t1;
78                     if(!vis[j]){
79                         vis[j] = 1;
80                         q1.push(j);
81                     }
82                 }
83         }
84     }
85     for(int i = 1 ; i <= M ; i++)
86         cout << fixed << setprecision(1) << peo[ans[i << 1].start][ans[i << 1].end] + 1e-8 << endl;
87     return 0;
88 }

 

转载于:https://www.cnblogs.com/Itst/p/10186886.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值