题意:
有0~n-1这几个城市是连通的,每个城市之间连接着一些道路,问有几种删除边(有可能不删除)的方案,使得这些城市还是连通的,剩下的边最少(即生成树,剩下n-1条边),对于每个城市,它们到0的最短路不变。
思路:
因为只能有n-1条边,所以对于每个点每次加边的时候只能加一条。
首先算出每个点到0的最短路,然后对于每个点找一个父节点,如果0到父节点的最短路+该点到父节点的距离=0到该点的最短路,就可以通过这个父节点来走,只多加了一条边,因为0到父节点的最短路是本来就存在的。这样遍历每个点,再把结果相乘,就是答案了。
代码:
typedef long long ll;
int g[110][110];
char a[110];
typedef pair<int,int>p;
int dis[110];
int n;
void dijkstra()
{
fill(dis,dis+n,INF);
dis[0]=0;
priority_queue<p,vector<p>,greater<p> >q;
q.push(p(0,0));
while(!q.empty())
{
p temp=q.top();
q.pop();
int w=temp.first;
int id=temp.second;
if(w>dis[id])continue;
for(int i=0;i<n;i++)
{
if(w+g[id][i]<dis[i])
{
dis[i]=w+g[id][i];
q.push(p(dis[i],i));
}
}
}
//for(int i=0;i<n;i++)
//printf("%d ",dis[i]);
//printf("\n");
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
for(int i=0;i<n;i++)
{
scanf("%s",a);
for(int j=0;j<n;j++)
{
g[i][j]=a[j]-'0';
if(i!=j&&g[i][j]==0)g[i][j]=INF;
}
}
dijkstra();
ll ans=1;
for(int i=1;i<n;i++)
{
ll temp=0;
for(int j=0;j<n;j++)
{
if(i!=j&&dis[j]+g[i][j]==dis[i])
temp++;
}
//printf("%lld\n",temp);
ans=(ans*temp)%MOD;
}
printf("%lld\n",ans);
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!