BZOJ从入门到入土
- [Jsoi2010]连通数:有向图求每一个点到能到达的点的个数的和(包括自己到自己)
SCC+bitset+dp
#include<bits/stdc++.h>
using namespace std;
// 方法:SCC + bitset传递闭包 或 直接bitset优化floyd
/**
* 1. tarjan板子复习
* 2. tarjan缩点重建图复习
* 3. 利用bitset求传递闭包(更快,因为可以直接按位或)
* 4. bitset优化floyd
*/
vector<int> h[2010]; // 原图的邻接表
// tarjan需要的变量
stack<int> stk;
int dfn[2010], low[2010], instk[2010], idx;
int SCC[2010], cnt; // 每一个点所在的SCC编号、SCC的个数
int SIZE[2010]; // 每一个SCC中包含的点数
vector<int> scc[2010]; // 新图的邻接表
bitset<2010> g[2010]; // 用于求新图的传递闭包的bitset对于每一个点开一个bitset, 传递闭包直接或
void tarjan(int u){
dfn[u] = low[u] = ++ idx;
instk[u] = 1;
stk.push(u);
for(auto j : h[u]){
if(!dfn[j]){
tarjan(j);
low[u] = min(low[u], low[j]);
}else if(instk[j] && dfn[j] < low[u])
low[u] = dfn[j];
}
if(low[u] == dfn[u]){
cnt ++;
int num = 0;
do{
num ++;
int t = stk.top();
SCC[t] = cnt;
instk[t] = 0;
stk.pop();
if(t == u) break;
}while(1);
SIZE[cnt] = num; // 当前SCC中包含的点数
}
}
bitset<2010> dfs(int u){
if(g[u] != 0) return g[u];
g[u][u] = 1;
for(auto v : scc[u]){
g[u] |= dfs(v);
}
return g[u];
}
void solve(){
int n;
cin >> n;
// 建立原图的邻接表
for(int i = 0; i < n; i ++){
for(int j = 0; j < n; j ++){
char c;
cin >> c;
if(c == '1') h[i].push_back(j);
}
}
// SCC
for(int i = 0; i < n; i ++)
if(dfn[i] == 0) tarjan(i);
// 重建图,需要遍历所有边
for(int i = 0; i < n; i ++){
for(int j = 0; j < h[i].size(); j ++){
if(SCC[i] != SCC[h[i][j]]) scc[SCC[i]].push_back(SCC[h[i][j]]);
}
}
int ans = 0;
for(int i = 1; i <= cnt; i ++){ // SCC是从1开始编号的
auto k = dfs(i); // 求从i出发能到达的点的bitset
for(int j = 1; j <= cnt; j ++) // 遍历bitset
if(k[j])
ans += SIZE[i] * SIZE[j];
}
cout << ans << endl;
}
signed main(){
solve();
}
bitset+floyd
#include<bits/stdc++.h>
using namespace std;
bitset<2010> g[2010];
void solve(){
int n;
cin >> n;
for(int i = 0; i < n; i ++){
string s;
cin >> s;
reverse(s.begin(), s.end());
g[i] = bitset<2010>(s);
g[i][i] = 1;
}
for(int k = 0; k < n; k ++)
for(int i = 0; i < n; i ++)
if(g[i][k]) g[i] |= g[k];
int ans = 0;
for(int i = 0; i < n; i ++){
ans += g[i].count();
}
cout << ans << endl;
}
signed main(){
solve();
}