graph HDU - 5607(矩阵快速幂+K步可达路径)

graph HDU - 5607

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$.
分析:

实际上题目就是求K步可达路径,直接矩阵快速幂即可,只不过这里初始矩阵中存的不是0,1而是概论

a[i][j]ij1a[i][j]=1out[i]out[i]iij 原 来 a [ i ] [ j ] 表 示 i 可 以 到 达 j 则 为 1 , 现 在 a [ i ] [ j ] = 1 o u t [ i ] 其 中 o u t [ i ] 表 示 i 点 的 出 度 , 那 么 此 时 就 变 成 了 从 i 点 到 达 j 点 的 概 率

然后直接矩阵快速幂即可,注意输出格式很无聊

最后一行有空格,而且每次询问中间隔一行

code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9+7;
const int N = 60;
struct Matrix{
    ll m[N][N];
};
int n,m;
ll out[N];
Matrix mul(Matrix a,Matrix b){
    Matrix ans;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            ans.m[i][j] = 0;
            for(int k = 1; k <= n; k++){
                ans.m[i][j] = (ans.m[i][j] + a.m[i][k] * b.m[k][j] % mod) % mod;
            }
        }
    }
    return ans;
}
Matrix mq_pow(Matrix a,ll b){
    Matrix ans;
    memset(ans.m,0,sizeof(ans.m));
    for(int i = 1; i <= n; i++){
        ans.m[i][i] = 1;
    }
    while(b){
        if(b & 1)
            ans = mul(ans,a);
        b >>= 1;
        a = mul(a,a);
    }
    return ans;
}
ll q_pow(ll a,ll b){
    ll ans = 1;
    while(b){
        if(b & 1)
            ans = ans * a % mod;
        b >>= 1;
        a = a * a % mod;
    }
    return ans;
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        memset(out,0,sizeof(out));
        Matrix a;
        memset(a.m,0,sizeof(a.m));
        for(int i = 1; i <= m; i++){
            int x,y;
            scanf("%d%d",&x,&y);
            out[x]++;
            a.m[x][y] = 1;
        }
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= n; j++){
                if(a.m[i][j]){
                    a.m[i][j] = q_pow(out[i],mod-2);
                }
            }
        }
        int q;
        scanf("%d",&q);
        while(q--){
            int u,K;
            scanf("%d%d",&u,&K);
            Matrix ans = mq_pow(a,K);
            for(int i = 1; i <= n; i++){
                printf("%lld ",ans.m[u][i]);
            }
            puts("");
        }
    }
    return 0;
}
void DFSTraverse(Graph graph) { for (int i = 1; i <= graph->vexnum; i++) visited[i] = false; for (int i = 1; i <= graph->vexnum; i++) { if (!visited[i]) DFS(graph, i); } } void DFS(Graph graph, int v) { visited[v] = true; cout << graph->list[v].data << " "; Node* header = graph->list[v].head; while (header) { if (!visited[header->vex]) { DFS(graph, header->vex); } header = header->next; } } void BFSTraverse(Graph graph) { queue<int> MyQueue; for (int i = 1; i <= graph->vexnum; i++) visited[i] = false; for (int i = 1; i <= graph->vexnum; i++) { if (!visited[i]) { visited[i] = true; cout << graph->list[i].data << " "; MyQueue.push(i); while (!MyQueue.empty()) { int front = MyQueue.front(); MyQueue.pop(); Node* header = graph->list[front].head; while (header) { if (!visited[header->vex]) { visited[header->vex] = true; cout << graph->list[header->vex].data << " "; MyQueue.push(header->vex); } header = header->next; } } } } } void printGraph(Graph graph) { int** arr = new int* [graph->vexnum + 1]; for (int i = 1; i <= graph->vexnum; i++) { arr[i] = new int[graph->vexnum + 1]; } for (int i = 1; i <= graph->vexnum; i++) { for (int j = 1; j <= graph->vexnum; j++) { arr[i][j] = 0; } } for (int i = 1; i <= graph->vexnum; i++) { Node* header = graph->list[i].head; while (header) { arr[i][header->vex] = header->weight; header = header->next; } } for (int i = 1; i <= graph->vexnum; i++) { for (int j = 1; j <= graph->vexnum; j++) { cout << arr[i][j] << " "; } cout << endl; } }代码讲解
最新发布
06-09
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值