OI游戏
Time Limit: 1 Sec Memory Limit: 64 MBSubmit: 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
2
01
10
Input2
4
0123
1012
2101
3210
Sample Output
Output1
1
Output2
6
1
Output2
6
HINT
Source
记录方案,乘法原理
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 }