bzoj 5056: OI游戏 最短路树的计数

Posted Kaiser

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 5056: OI游戏 最短路树的计数相关的知识,希望对你有一定的参考价值。

OI游戏

Time Limit: 1 Sec  Memory Limit: 64 MB
Submit: 196  Solved: 159
[Submit][Status][Discuss]

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

HINT

 

Source

[Submit][Status][Discuss]


HOME Back

 

记录方案,乘法原理

 1 #include<cstring>
 2 #include<cmath>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstdio>
 6 #include<queue>
 7 
 8 #define N 57
 9 #define M 2507
10 #define mod 1000000007
11 #define ll long long
12 #define inf 1000000007
13 using namespace std;
14 inline int read()
15 {
16     int x=0,f=1;char ch=getchar();
17     while(ch<0||ch>9){if (ch==-) f=-1;ch=getchar();}
18     while(ch>=0&&ch<=9){x=(x<<3)+(x<<1)+ch-0;ch=getchar();}
19     return x*f;
20 }
21 
22 int n;
23 int cnt,hed[N],nxt[M],rea[M],val[M];
24 int dis[N],flag[N];
25 char ch[57];
26 
27 void add(int u,int v,int z)
28 {
29     nxt[++cnt]=hed[u];
30     hed[u]=cnt;
31     rea[cnt]=v;
32     val[cnt]=z;
33 }
34 void Spfa()
35 {
36     for (int i=1;i<=n;i++)
37         dis[i]=inf,flag[i]=0;
38     queue<int>q;q.push(1);dis[1]=0,flag[1]=1;
39     while(!q.empty())
40     {
41         int u=q.front();q.pop();
42         for (int i=hed[u];i!=-1;i=nxt[i])
43         {
44             int v=rea[i],fee=val[i];
45             if (dis[v]>dis[u]+fee)
46             {
47                 dis[v]=dis[u]+fee;
48                 if (!flag[v])
49                 {
50                     q.push(v);
51                     flag[v]=1;
52                 }
53             }
54         }
55         flag[u]=0;
56     }
57 }
58 int main()
59 {
60     memset(hed,-1,sizeof(hed));
61     n=read();
62     for (int i=1;i<=n;i++)
63     {
64         scanf("%s",ch+1);
65         int t=strlen(ch+1);
66         for (int j=1;j<=t;j++)
67             if (ch[j]!=0) add(i,j,ch[j]-0);
68     }
69     Spfa();
70     ll ans=1;
71     for (int i=2;i<=n;i++)
72     {
73         ll tot=0;
74         for (int j=hed[i];j!=-1;j=nxt[j])
75         {
76             int v=rea[j],fee=val[j];
77             if (dis[i]==dis[v]+fee) tot++;
78         }
79         ans=(ans*tot)%mod;
80     }
81     printf("%lld",ans);
82 }

 

以上是关于bzoj 5056: OI游戏 最短路树的计数的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2750最短路计数

bzoj2464: 中山市选[2009]小明的游戏(最短路)

2017-2018OI学习记录

BZOJ 2118 墨墨的不等式 数论 + 最短路 + 计数

[bzoj2125]最短路

BZOJ 2118 墨墨的等式(最短路)