【BZOJ5056】OI游戏 最短路+有向图生成树计数

【BZOJ5056】OI游戏

Description

小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的你来说,这不过是小菜一碟啦!

Input

第一行一个整数N,代表原图结点。
接下来N行,每行N个字符,描绘了一个邻接矩阵。邻接矩阵中,
如果某一个元素为0,代表这两个点之间不存在边,
并且保证第i行第i列的元素为0,第i行第j列的元素(i≠j)等于第j行第i列的元素。
2≤N≤50

Output

一行一个整数,代表删法总方案数膜1,000,000,007的结果。

Sample Input

Input1
2
01
10
Input2
4
0123
1012
2101
3210

Sample Output

Output1
1
Output2
6

题解:一开始看错题,以为是任意两点间的最短路都相同。。。

先求出1号点到所有点的最短路径图(如果1到所有点的最短路径都可能经过某条边,则这条边在最短路径图上)(注意这个图是有向的)(可以用SPFA或Dij,不过本人懒,用的Floyd)。然后我们只需要求出这个图的生成树个数了。由于要求的是外向树,所以用度数矩阵-邻接矩阵,再用辗转相除得到行列式的值即可。具体做法可以参见天赋那道题。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const ll P=1000000007;
int n;
char str[60];
int dis[60][60],map[60][60];
ll v[60][60],A,B;
ll ans;
int main()
{
	scanf("%d",&n);
	int i,j,k;
	for(i=1;i<=n;i++)
	{
		scanf("%s",str+1);
		for(j=1;j<=n;j++)	dis[i][j]=str[j]-'0',map[i][j]=dis[i][j]=(!dis[i][j]&&i!=j)?(0x3f3f3f3f):dis[i][j];
	}
	for(k=1;k<=n;k++)	for(i=1;i<=n;i++)	for(j=1;j<=n;j++)	dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
	for(i=1;i<=n;i++)	for(j=1;j<=n;j++)	if(i!=j)
	{
		if(dis[1][i]+map[i][j]==dis[1][j])	v[j][j]++,v[i][j]--;
	}
	for(i=1;i<=n;i++)	for(j=1;j<=n;j++)	v[i][j]=(v[i][j]+P)%P;
	ans=1;
	for(i=2;i<=n;i++)
	{
		for(j=i;j<=n;j++)	if(v[j][i])	break;
		if(j!=i)	for(ans=P-ans,k=i;k<=n;k++)	swap(v[i][k],v[j][k]);
		for(j=i+1;j<=n;j++)
		{
			A=v[i][i],B=v[j][i];
			while(B)
			{
				ll tmp=A/B,temp=A;	A=B,B=temp%B;
				for(ans=P-ans,k=i;k<=n;k++)	v[i][k]=(v[i][k]-v[j][k]*tmp%P+P)%P,swap(v[i][k],v[j][k]);
			}
		}
		ans=ans*v[i][i]%P;
	}
	printf("%lld",ans);
	return 0;
}
posted @ 2017-09-27 20:23  CQzhangyu  阅读(529)  评论(0编辑  收藏  举报