数据这么水,跑SPFA也不会被卡哈哈哈。
首先看题,题目大意是在一个无向图中求构造不同的最小生成树的方法,对此引发思考:怎样才能满足题意(新图与原图的最短路长度一致)。
想了想,觉得暴力能够水过去,然后写了下T了,这不就是个最短路计数+组合数学乘法原理吗?
想法确定了,怎么写呢?
- SPFA跑出最短路
- 处理时每当遇到满足(dis[x]==dis[y]+z)的点就该点的ans++
- 每处理完一个点就令tot*=ans,记得取mod
这样,答案就出来啦
思路简单,码量较少,解法自然,是一道推荐一做的好题。
代码如下:
#include<bits/stdc++.h> #define ll long long #define HA 1000000007 #define ERP(i,a) for(int i=head[(a)];i;i=e[i].nxt) #define REP(i,a,b) for(int i=(a),edd=(b);i<=edd;++i) #define DRP(i,a,b) for(int i=(a),edd=(b);i>=edd;--i) using namespace std; const int _=51; inline int read(){ char ch=getchar(); int r=0,s=1; while(ch>57||ch<48)s=ch==45?0:s,ch=getchar(); while(ch>=48&&ch<=57)r=r*10+ch-48,ch=getchar(); return s?r:-r; } queue< int > q; int n; int g[_][_],dis[_],vis[_],ans[_]; void init(){ memset(dis,0x7f,sizeof(dis)); n=read(); REP(i,1,n)REP(j,1,n)scanf("%1d",&g[i][j]); ans[1]=1; return; } void spfa(int s){ dis[s]=0,vis[s]=1,q.push(s); while(q.size()){ int x=q.front();vis[x]=0,q.pop(); REP(i,1,n){ if(!g[x][i])continue; if(dis[i]>dis[x]+g[x][i]){ dis[i]=dis[x]+g[x][i]; if(!vis[i])q.push(i),vis[i]=1; } } } return; } void solve(){ spfa(1); ll tot=1; REP(i,2,n){ REP(j,1,n){ if(!g[i][j])continue; if(dis[i]==dis[j]+g[i][j])ans[i]++; } tot=(tot*ans[i])%HA; } printf("%lld ",tot); return; } int main(){ init(); solve(); return 0; }