「一本通3.1 例1」黑暗城堡 题解

一句话题意:

给出一张无向图,求它的以1为根的最短路径生成树个数。

(答案对2147483647取模)

按说这题是放在最小生成树一章里面的,正解也应该是最小生成树之类的东西。

然而我太弱了,并不会用最小生成树解这题。

(以下的瞎扯如果有错的,欢迎在评论区批评指正orz)

算法一:乱搞

首先,既然是求最短路径树的个数,我们肯定要用到最短路径。

所以以1为起点跑一遍最短路,dijkstra和spfa都可以。

我们应该如何统计答案呢?

首先我们可以很容易地想到,在原图中,与最短路径无关的边是不参与答案统计的。

那么与最短路径有关的边是如何参与答案统计的呢?

扫描二维码关注公众号,回复: 7182055 查看本文章

首先我们知道,每一条与最短路径有关的边都可以参与最短路径树的生成。

其次我们知道,最短路径树是一个完整的连通块。

我们假设有一个最短路径树,现在将它的其中一个叶子节点割掉。

考虑如何将它重新变为一棵最短路径树。

很显然,每一个指向那个节点的最短路径边都可以做到这件事情,答案是形成那个被割掉的树的方案数乘以那个叶子节点的入度。

反过来思考,最短路径树的形成实际上就是一个递归过程,每个节点(除了根节点1)都要收到同样的待遇。

所以答案就是所有节点(除了1)关于最短路径边的入度乘起来。

哦对了,无向边要割成两条有向边处理。

下面附上我丑陋的代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <queue>
 4 using namespace std;
 5 
 6 struct node{
 7     int to,next,len;
 8 }e[1000005];
 9 
10 int cnt=0,n,m;
11 int head[1005],dis[1005][2],xx[500005],yy[500005],ll[500005];
12 long long int statistics[1005];
13 bool vis[1005];
14 
15 void add(int from,int to,int len){
16     e[++cnt].to=to;
17     e[cnt].len=len;
18     e[cnt].next=head[from];
19     head[from]=cnt;
20 }
21 
22 inline void spfa(bool statue){
23     queue<int> q;
24     q.push(1);
25     dis[1][statue]=0;
26     vis[1]=1;
27     
28     while(!q.empty()){
29         int now=q.front();
30         vis[now]=0;
31         q.pop();
32         
33         for(int i=head[now];i;i=e[i].next){
34             if(dis[e[i].to][statue]>dis[now][statue]+e[i].len){
35                 dis[e[i].to][statue]=dis[now][statue]+e[i].len;
36                 if(vis[e[i].to]==0){
37                     vis[e[i].to]=1;
38                     q.push(e[i].to);
39                 }
40             }
41         }
42     }
43 }
44 
45 void handle(){
46     for(int i=1;i<=m;i++){
47         if(dis[xx[i]][0]==dis[yy[i]][0]+ll[i])    statistics[xx[i]]++;
48         if(dis[yy[i]][0]==dis[xx[i]][0]+ll[i])    statistics[yy[i]]++;
49     }
50 }
51 
52 int main(void){
53     memset(dis,0x3f,sizeof(dis));
54     
55     scanf("%d%d",&n,&m);
56     for(int i=1;i<=m;i++){
57         int x,y,l;
58         scanf("%d%d%d",&x,&y,&l);
59         add(x,y,l);
60         add(y,x,l);
61         xx[i]=x,yy[i]=y,ll[i]=l;
62     }
63     
64     spfa(0);
65     handle();
66     
67     long long int ans=1;
68     for(int i=2;i<=n;i++)    ans*=statistics[i],ans%=(1ll<<31)-1;
69     printf("%lld",ans);
70 }

未完待续。。。

猜你喜欢

转载自www.cnblogs.com/Pride205/p/11465434.html