思路来源
https://blog.csdn.net/mengxiang000000/article/details/72801224
题意
n个点,输入它的邻接矩阵形式,注意0是没有边,其余对应数为其权值。
求删边方案数,使得删完边之后是一颗生成树,且所有点到0号点的最短路是不删边之前的最短路。
n<=50(数据好弱的说)
题解
先dijkstra跑一遍最短路,然后开始统计对任意一个节点,其最短路径的条数。
注意到,若出现dis[v]==dis[u]+w时,说明出现路径相同的两条,但该长度可能不是最短路。
所以我们每次dis[v]>dis[u]+w更新最短路时,就将in[]数组置0,
之后每次相同就++,统计除当前最短外还有相同长度路径的条数。
最后ans=每个路径的最短路条数之积,即
注意到一棵生成树只差一个点时,若一个点能从已知树上点与该树建边,则树上已存点和该点的父子关系是确定的。
树上最短路是恒定的,说明若dis[v]==dis[u]+w时,dis[u]是不可能dis[v]+w的,
所以一条边最多只对一个点的最短路径有贡献,我们模拟点的插入过程,
统计每个点到树的最短路路径条数,即每个点到最短路树的出度即可。
心得
ans=每个路径的最短路条数之积这个想了很久,
后来才发现,树上最短路的关系不是相对的,即已知最短路只能扩展到其儿子。
我们在统计一个点的时候,将当前树形固定下来即可。
代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
#include <functional>
const int INF=0x3f3f3f3f;
const int maxn=1e5+10;
const int mod=1e9+7;
const int MOD=998244353;
const double eps=1e-7;
typedef long long ll;
#define vi vector<int>
#define si set<int>
#define pii pair<double,int>
#define pi acos(-1.0)
#define pb push_back
#define mp make_pair
#define lowbit(x) (x&(-x))
#define sci(x) scanf("%d",&(x))
#define scll(x) scanf("%lld",&(x))
#define sclf(x) scanf("%lf",&(x))
#define pri(x) printf("%d",(x))
#define rep(i,j,k) for(int i=j;i<=k;++i)
#define per(i,j,k) for(int i=j;i>=k;--i)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int head[1005],cnt,n,in[1005],dis[1005];
char tmp[1005];
bool vis[1005];
struct edge{int to,nex,w;}e[1<<20];
priority_queue<pii,vector<pii>,greater<pii> >q;
void init()
{
cnt=0;
mem(dis,INF);
mem(head,-1);
mem(vis,0);
mem(in,0);
}
void add(int u,int v,double w)
{
e[cnt].to=v;
e[cnt].w=w;
e[cnt].nex=head[u];
head[u]=cnt++;
}
void dijkstra(int u)
{
dis[u]=0;
q.push(pii(0,0));
while(!q.empty())
{
pii tmp=q.top();
q.pop();
int fi=tmp.first,se=tmp.second;
if(vis[se])continue;
vis[se]=1;
for(int i=head[se];~i;i=e[i].nex)
{
int v=e[i].to,w=e[i].w;
if(dis[v]>dis[se]+w)
{
dis[v]=dis[se]+w;
q.push(pii(dis[v],v));
in[v]=0;
}
else if(dis[v]==dis[se]+w)
{
in[v]++;
}
}
}
}
int main()
{
while(~scanf("%d",&n))
{
init();
rep(i,0,n-1)
{
scanf("%s",tmp);
rep(j,0,n-1)
{
if(tmp[j]=='0')continue;
else add(i,j,tmp[j]-'0');
}
}
dijkstra(0);
ll ans=1;
rep(i,1,n-1)
{
ans*=(1+in[i]);
if(ans>=mod)ans%=mod;
}
printf("%lld\n",ans);
}
return 0;
}