您的位置:首页 > 其它

hdoj 5607 graph 【矩阵快速幂】

2016-01-02 22:08 183 查看

graph

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 103    Accepted Submission(s): 53


Problem Description

In a directed graph which has N points
and M edges,points
are labled from 1 to n.At first I am at point u,at
each step I will choose an output edge of the current point at uniform random,for every point Z,please
output the possibility of reaching the point Z,moving
exactly K steps.

 

Input

the first line contains two positive intergesN,M,means
the number of points and edges.

next M lines,contains
two positive intergersX,Y,means
an directed edge from X to Y.

next line there is an integer Q,means
the number of queries.

next Q lines,each
line contains two integers u,K,means
the first point and number of the steps.

N≤50,M≤1000,Q≤20,u≤N,K≤109.

Every point have at least one output edge.
 

Output

Q lines,each
line contains N numbers,the i-th
number means the possibility of reaching point i from u,moving
exactly K steps.

In consideration of the precision error,we make some analyses,finding the answer can be represented as the form like XY,you
only need to output X×Y109+5 mod (109+7).

You need to output an extra space at the end of the line,or you will get PE.
 

Sample Input

3 2
1 2
1 3
1
1 1

 

Sample Output

0 500000004 500000004

I am now at point $1$,by one move,with a possibity of $\frac{1}{2}$ of reaching point 2,with a possibity of $\frac{1}{2}$ of reaching point 3,so we need to output 0 0.5 0.5,but as what is said above,we need to output$1*2^{10^9+5}~mod~{10^9+7}=500000004$.

 

问题描述
在一个NN个点(标号11~nn),MM条边的有向图上,一开始我在点uu,每一步我会在当前点的出边中等概率的选一条走过去,求走了恰好KK步后走到每个点的概率.


输入描述
第一行两个正整数N,MN,M,表示点数和边数.
接下来MM行,每行两个正整数X,YX,Y.表示一条XX向YY的一条有向边(保证没有重边和自环).
接下来一个正整数QQ,表示询问个数.
接下来QQ行,每行两个正整数u,Ku,K,表示开始的点和步数.
N \leq 50, M \leq 1000, Q \leq 20, u \leq n, K \leq 10^{9}N≤50,M≤1000,Q≤20,u≤n,K≤10​9​​.
每个点保证至少有一个出边.


输出描述
QQ行,每行NN个数字,用空格隔开,第ii个数字表示从uu开始走KK步到ii的概率.
考虑到输出的答案可能会有精度问题,经过一定的分析后可以发现答案一定可以被表示成\frac{X}{Y}​Y​​X​​的形式,你只需输出X \times Y^{10^9+5} \ mod \ (10^9+7)X×Y​10​9​​+5​​ mod (10​9​​+7)的值即可.

在每行后面多输出一个空格,否则可能会使你PE.


输入样例
3 2
1 2
1 3
1
1 1


输出样例
0 500000004 500000004


Hint
这是一个三个点,两条边的有向图,它们分别是(1->2,1->3)(1−>2,1−>3).现在在1号点,走了一步后,有1/2的概率走到了2,有1/2的概率走到了3,本来应该输出 0 0.5 0.5
而根据上面所说的,应输出1*2^{10^9+5} \ mod \ (10^9+7)=5000000041∗2​10​9​​+5​​ mod (10​9​​+7)=500000004.


只能说自己太SB了!!!

思路:设置P[k][i]为第k步到达i点的概率。

那么P[k+1][i] = sigma(P[k][j] * idv(degree[j])) (1 <= j <= N && Map[j][i] == 1)。

求的时候设个逆元就好了,最后结果是一样的。 

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <string>
#define INF 0x3f3f3f3f
#define eps 1e-8
#define MAXN (50+10)
#define MAXM (500000)
#define Ri(a) scanf("%d", &a)
#define Rl(a) scanf("%lld", &a)
#define Rf(a) scanf("%lf", &a)
#define Rs(a) scanf("%s", a)
#define Pi(a) printf("%d\n", (a))
#define Pf(a) printf("%.2lf\n", (a))
#define Pl(a) printf("%lld\n", (a))
#define Ps(a) printf("%s\n", (a))
#define W(a) while(a--)
#define CLR(a, b) memset(a, (b), sizeof(a))
#define MOD 1000000007
#define LL long long
#define lson o<<1, l, mid
#define rson o<<1|1, mid+1, r
#define ll o<<1
#define rr o<<1|1
#define PI acos(-1.0)
using namespace std;
struct MATRIX{
struct Matrix{
LL a[MAXN][MAXN];
int r, c;
};
Matrix ori, res;
Matrix multi(Matrix x, Matrix y)
{
Matrix z; CLR(z.a, 0);
z.r = x.r; z.c = y.c;
for(int i = 1; i <= x.r; i++)
{
for(int k = 1; k <= x.c; k++)
{
if(x.a[i][k] == 0) continue;
for(int j = 1; j <= y.c; j++)
z.a[i][j] = (z.a[i][j] + x.a[i][k] * y.a[k][j] % MOD) % MOD;
}
}
return z;
}
Matrix Pow(Matrix z, int n)
{
Matrix x; x.r = z.r; x.c = z.c;
for(int i = 1; i <= x.r; i++)
for(int j = 1; j <= x.c; j++)
x.a[i][j] = z.a[i][j];
Matrix y; y.r = y.c = z.r;
CLR(y.a, 0);
for(int i = 1; i <= y.r; i++)
y.a[i][i] = 1;
while(n)
{
if(n & 1)
y = multi(y, x);
x = multi(x, x);
n >>= 1;
}
return y;
}
};
MATRIX solve;
void exgcd(LL a, LL b, LL &d, LL &x, LL &y)
{
if(!b) {d = a, x = 1, y = 0;}
else
{
exgcd(b, a%b, d, y, x);
y -= x * (a / b);
}
}
LL inv(LL a)
{
LL d, x, y;
exgcd(a, MOD, d, x, y);
return (x + MOD) % MOD;
}
int degree[MAXN];
bool Map[MAXN][MAXN];
int main()
{
int N, M;
while(scanf("%d%d", &N, &M) != EOF)
{
CLR(degree, 0); CLR(Map, false);
for(int i = 0; i < M; i++)
{
int a, b;
Ri(a); Ri(b);
Map[a][b] = true;
degree[a]++;
}
for(int i = 1; i <= N; i++)
{
LL P = inv((LL)degree[i]);
for(int j = 1; j <= N; j++)
if(Map[i][j])
solve.ori.a[i][j] = P;
}
solve.ori.r = solve.ori.c = N;
int Q; Ri(Q);
W(Q)
{
int u, k;
Ri(u); Ri(k);
solve.res = solve.Pow(solve.ori, k);
for(int i = 1; i <= N; i++)
printf("%I64d ", solve.res.a[u][i]);
printf("\n");
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: