1. 程式人生 > >給定一個有向圖,問從A點恰好走k步(允許重複經過邊)到達B點的方案數---矩陣乘法

給定一個有向圖,問從A點恰好走k步(允許重複經過邊)到達B點的方案數---矩陣乘法

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string.h>
#include <vector>
#include <queue>    //hdu2157
#define mod 1000 
using namespace std;
/*
題目大意:給定一個有向圖,問從A點恰好走k步(允許重複經過邊)到達B點的方案數mod p的值
把給定的圖轉為鄰接矩陣,即A(i,j)=1當且僅當存在一條邊i->j。令C=A*A,那麼C(i,j)=ΣA(i,k)*A(k,j),
實際上就等於從點i到點j恰好經過2條邊的路徑數(列舉k為中轉點。
類似地,C*A(這裡的C已經是A*A)的第i行第j列就表示從i到j經過3條邊的路徑數。同理,如果要求經過k步的 路徑數,我們只需要二分求出A^k即可。
注意:矩陣多次冪可以防止爆棧(相比二分法求矩陣多次冪)
*/
int n;
struct matrix
{
	int a[25][25];
	void init()
	{
		for(int j=0; j<25; ++j)
		{
			for(int t=0; t<25; ++t)
				a[j][t]=0;
		}
	}
}p;

matrix mul(matrix a1, matrix b1)
{
	matrix q;
	q.init();
	int t, j, k;
	for(j=0; j<n; ++j)
	{
		for(t=0; t<n; ++t)
		{
			for(k=0; k<n; ++k)
			{
				q.a[j][t]+=a1.a[j][k]*b1.a[k][t];
				q.a[j][t]%=mod;
			}
		}
	}
	return q;
}
/*			
matrix f(int x)   如果用二分法來求矩陣快多次冪,需要遞迴多次(每遞迴一次就要申請一個矩陣空間),這樣很容易爆棧
{
	if(x==1)return p;
	matrix s=f(x/2);
	s=mul(s, s);
	if(x&1)
		s=mul(s, p);
	return s;
}
*/

matrix f(int x)   //矩陣多次冪可以防止爆棧
{
	matrix q, s=p;
	int t, j;
	for(j=0; j<n; ++j)    //構建單位矩陣
	{
		for(t=0; t<n; ++t)
		{
			if(j==t)
				q.a[j][t]=1;
			else q.a[j][t]=0;
		}
	}
	while(x)
	{
		if(x&1)
			q=mul(s, q);
		x=x>>1;
		s=mul(s, s);
	}
	return q;
}

int main()
{
	int m ,t, T, s, k, s1, s2, g;
	while(scanf("%d%d", &n, &m)!=EOF)
	{
		if(n==0&&m==0)break;
		p.init();
		for(t=0; t<m; ++t)
		{
			scanf("%d%d", &s, &g);
			p.a[s][g]=1;    //有向的
		}
		scanf("%d", &T);
		while(T--)
		{
			scanf("%d%d%d", &s1, &s2, &k);
			matrix result=f(k);
			printf("%d\n", result.a[s1][s2]);  //s1到s2的路徑總數
		}
	}
	return 0;
}

相關推薦

給定一個A好走k允許重複經過到達B方案---矩陣乘法

#include <iostream> #include <cstdio> #include <algorithm> #include <cmath>

[阿里筆試]以下是一個我們節點B開始進行深度優先遍歷DFS那麼以下5個序列中所有正確的DFS序列是____。

題目(阿里筆試題):以下是一個有向圖,我們從節點B開始進行深度優先遍歷(DFS),那麼以下5個序列中,所有正確的DFS序列是__。 解析:深度優先遍歷是指優先探索完一條通路後才返回倒數第二個節點繼

Toposort Description    給出一個判斷中是否存在迴路。 Input:   第1行:輸入的頂點個數N1 ≤ N≤ 2,500和C1 ≤ C ≤ 6,20

Toposort Description 給出一個有向圖,判斷圖中是否存在迴路。 Input: 第1行:輸入圖的頂點個數N(1 ≤ N≤ 2,500)和C(圖的邊數,1 ≤ C ≤ 6,200); 第2到C+1行中,第i+1行輸入兩個整數,分別表示第i條邊的起點和終點的編號

uva11090 給你一個求出平均權值最小的環

B 【題目描述】  泡泡魚是一條調皮的魚,ta 的家住在一片珊瑚礁上。在 ta 的眼裡,這些珊瑚礁的形態 可以腦補成一個 n 個節點,m 條邊的帶權圖,在海水的腐蝕下,這些珊瑚礁形成了許多的 環,ta 想考考你能不能找出這些環中,權值的平均值最小的環。泡泡魚這麼聰明,ta

【HDU 4514】【樹的直徑 dfs或者並查集判斷環】【給定一個可能是非連通的如果中存在環就輸出YES否則就輸出樹的直徑】

描述: 湫湫系列故事——設計風景線 Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 4610    Acc

程式設計師面試金典: 9.4樹與 4.2給定設計一個演算法找出兩個節點之間是否存在一條路徑。

#include <iostream> #include <stdio.h> #include <vector> #include <queue> using namespace std; /* 問題:給定有向圖,設計一個

poj3615 給你一個,然後對於特定的AB,要你求出AB之間所有可行路徑的單段路距離最大值的最小值.

#include<cstdio> #include<algorithm> #define INF 1e9 using namespace std; const int maxn = 300+10; int n,m,t; int d[maxn][maxn]; void floy

poj3615 給你一個,然後對於特定的AB,要你求出AB之間所有可行路徑的單段路距離最大值的最小值.

#include<cstdio> #include<algorithm> #define INF 1e9 using namespace std; const int maxn = 300+10; int n,m,t; int d[maxn][maxn

用dfs判斷一個是否

解決這個問題的演算法的思路是對一個節點u進行dfs,判斷是否能從u回到自己這個節點,即是否存在從u到u的迴路。 我們可以用一個color陣列代表每個結點的狀態,-1代表還沒被訪問,0代表正在被訪問,1代

Kosaraju 演算法求解一個的強連通分支個數

基本介紹 網上看了很多關於求解一個有向圖的強連通分支個數的演算法,其中最著名的莫過於: Kosaraju 演算法 看的比較暈! 過程如下: 1。 建立一個空的棧 S,並做一次 DFS 遍歷。在 DFS 遍歷中,當在遞迴呼叫 DSF 訪問鄰接頂點時,將

Java鄰接表表示加權附dijkstra最短路徑演算法

圖這種adt(abstract data type)及相關的演算法,之前一直是我未曾涉足過的領域。 主要是作為一個小測試,在平常的工作中也用不著,就算面試,至今也未曾碰到過相關考題。 但是前幾天,原公司的小美女談到面試過程中就碰到一題: 從A到B,有多條路線,要找出最短路

一個G的拓撲序列

題目:已知有向圖G=(V,E),其中V={V1,V2,V3,V4,V5,V6,V7},E={(V1,V2),(V1,V3),(V1,V4),(V2,V5),(V3,V5),(V3,V6),(V4,V6

的鄰接矩陣表示C++實現(遍歷拓撲排序最短路徑最小生成樹) Implement of digraph and undigraph using adjacency matrix

本文實現了有向圖,無向圖的鄰接矩陣表示,並且實現了從建立到銷燬圖的各種操作。 以及兩種圖的深度優先遍歷,廣度優先遍歷,Dijkstra最短路徑演算法,Prim最小生成樹演算法,有向圖的拓撲排序演算法。 通過一個全域性變數控制當前圖為有向圖還是無向圖。 若為無向圖,則生成的

給定一個m*n的格子或棋盤左上角走到右下角的走法總數每次只能右或下移動一個方格長的距離。

比如一個2*3的矩陣, 1 2 3 4 5 6 從1出發走到6,則可能的走法為:1 2 3 6, 1 2 5 6, 1 4 5 6共有三種。 這道題可以看成是深度優先遍歷一顆樹。解法為: public class MatrixTraversal { public s

一個頂點到其餘各個頂點的最短路徑

目錄 從一個頂點到其餘各個頂點最短路徑的簡介 舉例以及詳細分析 程式碼塊 測試結果 從一個頂點到其餘各個頂點最短路徑的簡介(又名單元最短路徑) 1.定義概覽 Dijkstra(迪傑斯特拉)演算法是典型的單源最短路徑演算法,用於計算一個節點到其他所

DFS的運用二分判定、無的割頂和橋雙連通分量的強連通分量

part str stack void div prev this 沒有 2-sat 一、dfs框架: 1 vector<int>G[maxn]; //存圖 2 int vis[maxn]; //節點訪問標記 3 void dfs(int u

LeetCode 給定一個 N 叉樹找到其最大深度。 最大深度是指根節點到最遠葉子節點的最長路徑上的節點總數

/* // Definition for a Node. class Node { public:     int val;     vector<Node*> children;     Node() {}  

扇形角度調整。

clc clear all close all sensingR=18; coverSector=pi/3; Coverlength=50; %x=randi([1 50],1,30); %y=randi([1 50],1,30); % save initDeploy load initDeploy

給定一個正整數n求出0到n中幾個數滿足其二進位制表示不包含連續的1

樣例: 輸入:5 輸出:5 0 01 10 100 101滿足,11不滿足。 那麼6144呢? 答案是610,怎麼去計算呢? 思路:查詢從0到n中有多少個數包含連續的1,然後在總數中去掉這些情況,得到

實驗四+鄰接矩陣BFSDFS遞迴+非遞迴+鄰接表BFSDFS遞迴+非遞迴拓撲排序

//Sinhaeng Hhjian #include<bits/stdc++.h> using namespace std; const int N=100; const int MAX=1000; int book[N], cnt; struct node{