标签:
题意:给定一个有向图,求出该有向图中有多少个点对<x,y>,使x可以达到y。(x和y相等的情况也算)
首先,很显然,若a和b两个点在同一个强连通分量中,那么一定满足:
(1)a和b互相可达
(2)a能达到的点数和b能达到的点数相等
那么二话不说肯定是用tarjan缩点啦~点权自然是对应强连通分量的点个数
然后缩完点之后统计方案就不是很会了。。
一开始只想到了对缩点后的图跑一遍Floyd传递闭包,然后用乘法原理统计一下答案
然而这样的话时间复杂度就是O(n^3)了,那还不如不缩点直接原图跑传递闭包呢。。也是O(n^3)的
最后看了题解才知道怎么做。。对缩点后的dag跑dp。。
设F[i][j]为一个二进制位(每个F[i]都是一个bitset),表示能否从j达到i
然后初始化自然是F[i][i]=true
然后做拓扑排序,顺便跑动态规划。状态转移方程是F[j]|=F[i] (i与j之间有边)
最后答案就是所有的weight[i]*weight[j]之和 (weight是某个点的点权,并且F[i][j]为true)
1 #include <queue> 2 #include <stack> 3 #include <cstdio> 4 #include <bitset> 5 6 using namespace std; 7 8 const size_t Max_N(2050); 9 10 size_t N; 11 char Graph[Max_N][Max_N]; 12 13 unsigned int SCC_Total; 14 unsigned int SCC_Number[Max_N]; 15 unsigned int SCC_Graph[Max_N][Max_N]; 16 unsigned int SCC_Weight[Max_N]; 17 unsigned int SCC_Degree[Max_N]; 18 19 inline 20 unsigned int Min(const unsigned int &a, const unsigned int &b) 21 { 22 return a < b ? a : b; 23 } 24 25 void init() 26 { 27 scanf("%u", &N); 28 for (size_t i = 1;i <= N;++i) 29 { 30 scanf("%s", Graph[i] + 1); 31 for (size_t j = 1;j <= N;++j) 32 Graph[i][j] -= ‘0‘; 33 } 34 } 35 36 unsigned int Dfs_Clock; 37 unsigned int Pre[Max_N], Low_Link[Max_N]; 38 stack<unsigned int> S; 39 void Tarjan(const size_t &u) 40 { 41 size_t v; 42 43 Pre[u] = Low_Link[u] = ++Dfs_Clock; 44 S.push(u); 45 46 for (v = 1;v <= N;++v) 47 if (Graph[u][v]) 48 if (!Pre[v]) 49 { 50 Tarjan(v); 51 Low_Link[u] = Min(Low_Link[u], Low_Link[v]); 52 } 53 else 54 if (!SCC_Number[v]) 55 Low_Link[u] = Min(Low_Link[u], Pre[v]); 56 57 if (Pre[u] == Low_Link[u]) 58 { 59 ++SCC_Total; 60 while (true) 61 { 62 v = S.top(); 63 S.pop(); 64 SCC_Number[v] = SCC_Total; 65 ++SCC_Weight[SCC_Total]; 66 if (u == v) 67 break; 68 } 69 } 70 } 71 72 void Make_Graph() 73 { 74 for (size_t i = 1;i <= N;++i) 75 if (!Pre[i]) 76 Tarjan(i); 77 for (size_t s = 1;s <= N;++s) 78 for (size_t t = 1;t <= N;++t) 79 if (Graph[s][t] && SCC_Number[s] != SCC_Number[t]) 80 if (!SCC_Graph[SCC_Number[s]][SCC_Number[t]]) 81 { 82 SCC_Graph[SCC_Number[s]][SCC_Number[t]] = true; 83 ++SCC_Degree[SCC_Number[t]]; 84 } 85 } 86 87 bitset<Max_N> F[Max_N]; 88 queue<unsigned int> Q; 89 void dp() 90 { 91 for (size_t i = 1;i <= SCC_Total;++i) 92 F[i][i] = true; 93 for (size_t i = 1;i <= SCC_Total;++i) 94 if (!SCC_Degree[i]) 95 Q.push(i); 96 97 unsigned int Top; 98 while (Q.size()) 99 { 100 Top = Q.front(); 101 Q.pop(); 102 for (size_t i = 1;i <= SCC_Total;++i) 103 if (SCC_Graph[Top][i]) 104 { 105 --SCC_Degree[i]; 106 F[i] |= F[Top]; 107 if (!SCC_Degree[i]) 108 Q.push(i); 109 } 110 } 111 } 112 113 void Get_Ans() 114 { 115 unsigned int Ans(0); 116 for (size_t i = 1;i <= SCC_Total;++i) 117 for (size_t j = 1;j <= SCC_Total;++j) 118 if (F[i][j]) 119 Ans += SCC_Weight[i] * SCC_Weight[j]; 120 printf("%u", Ans); 121 } 122 123 int main() 124 { 125 init(); 126 127 Make_Graph(); 128 dp(); 129 Get_Ans(); 130 131 return 0; 132 }
标签:
原文地址:http://www.cnblogs.com/Created-equal/p/5024211.html