题目描述:
小Van的CP最喜欢玩与OI有关的游戏啦~小Van为了讨好她,于是冥思苦想,终于创造了一个新游戏。
下面是小Van的OI游戏规则:给定一个无向连通图,有 $N$ 个节点,编号为 $0$ ~ $N-1$ 。图里的每一条边都有一个正整数权值,边权在 $1$ ~ $9$ 之间。要求从图里删掉某些边(有可能 $0$ 条),使得剩下的图满足以下两个条件:1) 剩下的图是一棵树,有 $N-1$ 条边。2) 对于所有 $v (0<v<N)$ , $0$ 到 $v$ 的最短路(也就是树中唯一路径长度)和原图中的最短路长度相同。最终要报出有多少种不同的删法可以满足上述条件。(两种删法不同当且仅当存在两个点,一种删法删完之后这两个点之间存在边而另外一种删法不存在。)由于答案有可能非常大,良心的小Van只需要答案膜 $1,000,000,007$ 的结果。后记: 然而这游戏太高难度了,小Van的CP做不出来因此很不开心!她认为小Van在故意刁难她,于是她与小Van分手了。。。不过对于精通OI的你来说,这不过是小菜一碟啦!时间效率:$O(n^{2})$
以下代码:
#include#define il inline#define _(d) while(d(isdigit(ch=getchar())))using namespace std;const int N=55,inf=1e9,p=1e9+7;char s[N];bool vis[N];int n,a[N][N],d[N],f[N],ans=1;il int read(){ int x,f=1;char ch; _(!)ch=='-'?f=-1:f;x=ch^48; _()x=(x<<1)+(x<<3)+(ch^48); return f*x;}int main(){ n=read(); for(int i=1;i<=n;i++){ scanf(" %s",s+1); for(int j=1;j<=n;j++){ if(s[j]=='0'&&i!=j)a[i][j]=inf; else a[i][j]=s[j]-'0'; } } vis[1]=1; for(int i=1;i<=n;i++)d[i]=a[1][i],f[i]=1;d[0]=inf+1; for(int i=1;i<=n;i++){ int x=0; for(int j=1;j<=n;j++){ if(!vis[j]&&d[j]