题目大意:给一张无向图,求三元组$(u,v,w)$满足$u->v->w$为简单路径,求个数
题解:圆方树,缩点后$DP$,因为同一个点双中的点一定地位相同
卡点:1.$father$数组开小,一不小心就续到了下面的$bool$的$vis$数组中,然后就挂成$98$,因为发现去掉没用的$vis$数组变成$86$,才找到问题
C++ Code:
#include <cstdio>
#include <cstring>
#define maxn 100010
#define maxm 200010
#define N 200010
#define ONLINE_JUDGE
#define read() R::READ()
#include <cctype>
namespace R {
int x;
#ifdef ONLINE_JUDGE
char *ch, op[1 << 28];
inline void init() {
fread(ch = op, 1, 1 << 28, stdin);
}
inline int READ() {
while (isspace(*ch)) ch++;
for (x = *ch & 15, ch++; isdigit(*ch); ch++) x = x * 10 + (*ch & 15);
return x;
}
#else
char ch;
inline int READ() {
ch = getchar();
while (isspace(ch)) ch = getchar();
for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15);
return x;
}
#endif
}
int n, m;
long long ans;
inline int min(int a, int b) {return a < b ? a : b;}
namespace Tree {
int CNT;
int head[N], cnt;
struct Edge {
int to, nxt;
} e[N << 1];
void add(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
e[++cnt] = (Edge) {a, head[b]}; head[b] = cnt;
}
long long w[N], f[N], sz[N], pointsz;
int fa[N];
void dfs(int u) {
sz[u] = bool(u <= n);
long long tmp = 0;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v != fa[u]) {
fa[v] = u;
dfs(v);
tmp += sz[v] * sz[u];
sz[u] += sz[v];
}
}
tmp += sz[u] * (pointsz - sz[u]);
ans += w[u] * tmp << 1ll;
}
}
namespace Graph {
int head[maxn], cnt;
struct Edge {
int to, nxt;
} e[maxm << 1];
void add(int a, int b) {
e[++cnt] = (Edge) {b, head[a]}; head[a] = cnt;
e[++cnt] = (Edge) {a, head[b]}; head[b] = cnt;
}
int DFN[maxn], low[maxn], idx, fa[maxn];
int S[maxn], top;
void Tarjan(int u) {
Tree::pointsz++;
DFN[u] = low[u] = ++idx;
Tree::w[S[++top] = u] = -1;
int v;
for (int i = head[u]; i; i = e[i].nxt) {
v = e[i].to;
if (!DFN[v]) {
fa[v] = u;
Tarjan(v);
low[u] = min(low[u], low[v]);
if (low[v] >= DFN[u]) {
Tree::w[++Tree::CNT] = 1;
Tree::add(Tree::CNT, u);
do {
v = S[top--];
Tree::add(Tree::CNT, v);
Tree::w[Tree::CNT]++;
} while (v != e[i].to);
}
} else low[u] = min(low[u], DFN[v]);
}
}
inline void tarjan(int n) {
for (int i = 1; i <= n; i++) if (!DFN[i]) {
Tree::pointsz = 0;
Tarjan(i);
Tree::dfs(i);
}
}
}
int main() {
#ifdef ONLINE_JUDGE
R::init();
#endif
Tree::CNT = n = read(), m = read();
for (int i = 1; i <= m; i++) Graph::add(read(), read());
Graph::tarjan(n);
printf("%lld\n", ans);
return 0;
}