bzoj 5056
不想写题解...这题就是在跑最短路的时候记录下每个点最短路树上可能的父亲,然后把每个点的父亲数量乘起来就行了
代码:
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <vector> #define ll long long using namespace std; const ll mode=1000000007; struct Edge { int nxt; int to; int val; }edge[500005]; struct node { int p,v; node (){} node (int x,int y):p(x),v(y){} friend bool operator < (node a,node b) { return a.v>b.v; } }; int head[55]; int dis[55]; bool vis[55]; int cnt=1; char ch[55]; int n; vector <int> f[55]; void add(int l,int r,int w) { edge[cnt].nxt=head[l]; edge[cnt].to=r; edge[cnt].val=w; head[l]=cnt++; } void diji() { priority_queue <node> M; memset(dis,0x3f,sizeof(dis)); dis[1]=0; M.push(node(1,0)); while(!M.empty()) { node temp=M.top(); M.pop(); int u=temp.p; if(vis[u])continue; vis[u]=1; for(int i=head[u];i;i=edge[i].nxt) { int to=edge[i].to; if(dis[to]>dis[u]+edge[i].val) { f[to].clear(); f[to].push_back(u); dis[to]=dis[u]+edge[i].val; M.push(node(to,dis[to])); }else if(dis[to]==dis[u]+edge[i].val)f[to].push_back(u); } } ll ans=1; for(int i=2;i<=n;i++)ans=ans*f[i].size()%mode; printf("%lld\n",ans); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%s",ch+1); for(int j=1;j<=n;j++)if(ch[j]-'0'>0)add(i,j,ch[j]-'0'); } diji(); return 0; }