一些水水的模板啦啦(还在更..)
强连通分量缩点
BZOJ1051 [HAOI2006]受欢迎的牛
[HAOI2006]受欢迎的牛 の 传送门
强连通分量缩点模板题吧
//bzoj1051
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <stack>
using namespace std;
const int N = 10007, M = 50007;
int n, m, cnt, scc, tim, ans, head[N], to[M], nxt[M], low[N], dfn[N], belong[N], vis[N], hav[N], chu[N];
stack <int> S;
inline int read(){
int ans = 0, f = 1;
char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar())
if (ch == '-')
f = 0;
for(; ch >= '0' && ch <= '9'; ch = getchar())
ans = (ans << 3) + (ans << 1) + ch - 48;
return f? ans: -ans;
}
void add(int u, int v){
nxt[++cnt] = head[u];
to[cnt] = v;
head[u] = cnt;
}
void tarjan(int u){
dfn[u] = low[u] = ++tim;
S.push(u);
vis[u] = 1;
int v;
for (int i = head[u]; i; i = nxt[i]){
v = to[i];
if (!dfn[v])
tarjan(v), low[u] = min(low[u], low[v]);
else
if (vis[v])
low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]){
scc++;
do {
v = S.top();
vis[v] = 0;
belong[v] = scc;
hav[scc]++;
S.pop();
} while(u != v);
}
}
int main(){
tim = cnt = scc = 0;
n = read(), m = read();
while (S.size())
S.pop();
for (register int i = 1; i <= m; ++i){
int u = read(), v = read();
add(u, v);
}
for (register int i = 1; i <= n; ++i)
if (!dfn[i]) tarjan(i);
for (register int k = 1; k <= n; ++k)
for (int i = head[k]; i; i = nxt[i]){
int v = to[i];
if (belong[k] != belong[v])
chu[belong[k]]++;
}
ans = 0;
for (int i = 1; i <= scc; ++i){
if (!chu[i]){
if (ans){
printf("0\n");
return 0;
}
else
ans = hav[i];
}
}
printf("%d\n", ans);
return 0;
}
树上倍增求LCA
luogu3379
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
const int N = 500007, M = 500007;
int cnt, n, m, s, head[N], dep[N], fa[N][22], nxt[M << 1], to[M << 1];
inline int read(){
int ans = 0, f = 1;
char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar())
if (ch == '-')
f = 0;
for(; ch >= '0' && ch <= '9'; ch = getchar())
ans = (ans << 3) + (ans << 1) + ch - 48;
return f? ans: -ans;
}
void add(int u, int v){
nxt[++cnt] = head[u];
to[cnt] = v;
head[u] = cnt;
}
void dfs(int u, int father){
dep[u] = dep[father] + 1;
fa[u][0] = father;
for (int i = head[u]; i; i = nxt[i]){
int v = to[i];
if (v != father)
dfs(v, u);
}
}
int lca(int x, int y){
if (dep[x] < dep[y])
swap(x, y);
int z = dep[x] - dep[y];
for (int i = 0; i <= 20; ++i)
if (z & (1 << i))
x = fa[x][i];
for (int i = 20; i >= 0; --i)
if (fa[x][i] != fa[y][i]){
x = fa[x][i];
y = fa[y][i];
}
if (x == y)
return x;
return fa[x][0];
}
int main(){
n = read(), m = read(), s = read();
for (int i = 1; i < n; ++i){
int u = read(), v = read();
add(v, u);
add(u, v);
}
dfs(s, 0);
for (int j = 1; (1 << j) <= n; ++j)
for (int i = 1; i <= n; ++i)
fa[i][j] = fa[fa[i][j - 1]][j - 1];
for (int i = 1; i <= m; ++i){
int x = read(), y = read();
printf("%d\n", lca(x, y));
}
return 0;
}
最小生成树
Prim O(n^2)
luogu3366
//luogu3366
//Prim
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
const int N = 5007, M = 200007, oo = 1e9 + 7;
int n, m, cnt, num, head[N], to[M << 1], nxt[M << 1], val[M << 1], ans, dis[N];
bool vis[N];
inline int read(){
int ans = 0, f = 1;
char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar())
if (ch == '-')
f = 0;
for(; ch >= '0' && ch <= '9'; ch = getchar())
ans = (ans << 3) + (ans << 1) + ch - 48;
return f? ans: -ans;
}
void add(int u, int v, int w){
nxt[++cnt] = head[u];
to[cnt] = v;
val[cnt] = w;
head[u] = cnt;
}
void prim(){
memset(vis, false, sizeof(vis));
ans = 0;
dis[1] = 0;
for (int i = 2; i <= n; ++i)
dis[i] = oo;
num = 0;
while (num < n){
++num;
int minn = oo, now = -1;
for (int i = 1; i <= n; ++i)
if (!vis[i] && dis[i] < minn){
minn = dis[i];
now = i;
}
if (now == -1){
ans = -1;
return;
}
vis[now] = 1;
ans += dis[now];
for (int i = head[now]; i; i = nxt[i]){
int v = to[i];
if (!vis[v])
dis[v] = min(dis[v], val[i]);
}
}
}
int main(){
memset(head, 0, sizeof(head));
n = read(), m = read();
for (int i = 1; i <= m; ++i){
int u = read(), v = read(), w = read();
add(v, u, w);
add(u, v, w);
}
prim();
if (ans == -1)
printf("orz\n");
else
printf("%d\n", ans);
return 0;
}
Kruskal O(e*log e)
luogu3366
//luogu3366
//Kruskal
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
#define ll long long
using namespace std;
const int N = 5007, M = 200007, oo = 1e9 + 7;
int n, m, fa[N], cnt, ans;
struct iG{
int x, y, val;
} a[M];
inline int read(){
int ans = 0, f = 1;
char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar())
if (ch == '-')
f = 0;
for(; ch >= '0' && ch <= '9'; ch = getchar())
ans = (ans << 3) + (ans << 1) + ch - 48;
return f? ans: -ans;
}
inline bool cmp(iG a, iG b){
return a.val < b.val;
}
inline int find(int x){
return fa[x] == x ? x: fa[x] = find(fa[x]);
}
inline void kruskal(){
sort(a + 1, a + 1 + m, cmp);
for (register int i = 1; i <= n; ++i)
fa[i] = i;
for (register int i = 1; i <= m; ++i){
int fx = find(a[i].x), fy = find(a[i].y);
if (fx != fy){
ans += a[i].val;
fa[fx] = fy;
cnt++;
if (cnt == n - 1)
break;
}
}
}
int main(){
n = read(), m = read();
for (int i = 1; i <= m; ++i){
a[i].x = read(), a[i].y = read(), a[i].val = read();
}
kruskal();
if (cnt == n - 1)
printf("%d\n", ans);
else
printf("orz\n");
return 0;
}