Description
當今社會,在社交網絡上看朋友的消息已經成爲許多人生活的一部分。通常,一個用戶在社交網絡上發佈一條消息
(例如微博、狀態、Tweet等)後,他的好友們也可以看見這條消息,並可能轉發。轉發的消息還可以繼續被人轉
發,進而擴散到整個社交網絡中。在一個實驗性的小規模社交網絡中我們發現,有時一條熱門消息最終會被所有人
轉發。爲了研究這一現象發生的過程,我們希望計算一條消息所有可能的轉發途徑有多少種。爲了編程方便,我們
將初始消息發送者編號爲1,其他用戶編號依次遞增。該社交網絡上的所有好友關係是已知的,也就是說對於A、B
兩個用戶,我們知道A用戶可以看到B用戶發送的消息。注意可能存在單向的好友關係,即A能看到B的消息,但B不
能看到A的消息。
還有一個假設是,如果某用戶看到他的多個好友轉發了同一條消息,他只會選擇從其中一個轉發,最多轉發一次消
息。從不同好友的轉發,被視爲不同的情況。
如果用箭頭表示好友關係,下圖展示了某個社交網絡中消息轉發的所有可能情況。
初始消息是用戶1發送的,加粗箭頭表示一次消息轉發
Input
輸入文件第一行,爲一個正整數n,表示社交網絡中的用戶數:
第二行爲一個正整數m.表示社交網絡中的好友關係數目。
接下來m行,每行爲兩個空格分隔的整數ai和bi,表示一組好友關係,即用戶ai可以看到用戶bi發送的消息。
1≤n≤250,1≤ai,bi≤n,1≤m≤n(n-1)
Output
輸出文件共一行,爲一條消息所有可能的轉發途徑的數量,除以1 0007所得的餘數。
Sample Input
4
7
2 1
3 1
1 3
2 3
3 2
4 3
4 2
7
2 1
3 1
1 3
2 3
3 2
4 3
4 2
Sample Output
6
Solution
一眼矩陣樹定理模板題,省選出這個真的。
用出度矩陣和臨接矩陣相減構造基爾霍夫矩陣,求矩陣行列式。
Code
#include <iostream>
#include <cstdio>
#define R register
#define ll long long
using namespace std;
namespace Dntcry
{
inline int read()
{
R int a = 0, b = 1; R char c = getchar();
for(; c < '0'|| c > '9'; c = getchar()) (c == '-') ? b = -1 : 0;
for(; c >= '0' && c <= '9'; c = getchar()) a = (a << 1) + (a << 3) + c - '0';
return a * b;
}
const int Mod = 10007;
int n, m, Map[310][310], inv[10010], Ans;
int Guass()
{
R int res = 1;
for(R int i = 2, j; i <= n; i++)
{
for(j = i; !Map[j][i]; j++) ;
if(j > n) continue ;
if(j != i)
{
res = Mod - res;
for(R int k = i; k <= n; k++) swap(Map[i][k], Map[j][k]);
}
for(j = i + 1; j <= n; j++)
if(Map[j][i])
{
R int tmp = Map[j][i] * inv[Map[i][i]] % Mod;
for(R int k = i; k <= n; k++)
Map[j][k] = (Map[j][k] - tmp * Map[i][k] % Mod + Mod) % Mod;
}
}
for(R int i = 2; i <= n; i++) res = res * max(Map[i][i], 1) % Mod;
return res;
}
int Main()
{
n = read(), m = read();
inv[0] = inv[1] = 1;
for(R int i = 2; i < 10010; i++) inv[i] = (Mod - Mod / i) * inv[Mod % i] % Mod;
for(R int i = 1, u, v; i <= m; i++)
{
v = read(), u = read();
Map[v][v] = (Map[v][v] + 1) % Mod;
Map[u][v] = (Map[u][v] - 1) % Mod;
}
Ans = Guass();
printf("%d\n", Ans);
return 0;
}
}
int main() { return Dntcry :: Main(); }