#include<bits/stdc++.h> #define MAXN 100000 #define D 10 #define MAXM 10000010 using std::cin; using std::cout; using std::endl; int m, n;//m为边数,n为点数 //图的存储 //邻接矩阵 int a[5010][5010]; void init() { cin >> n >> m; for (int i = 1; i <= m; i++) { int x, y; cin >> x >> y; a[x][y] = 1; } } //边表 struct node { int x, y; } edge[MAXM + D]; void init() { cin >> n >> m; for (int i = 1; i <= m; ++i) cin >> edge[i].x >> edge[i].y; } //前向星 struct node { int x, y; } edge[500010]; int st[MAXN + D], en[MAXN + D]; inline bool cmp(node x, node y) { return x.x < y.y; } void init() { cin >> n >> m; for (int i = 1; i <= m; ++i) cin >> edge[i].x >> edge[i].y; std::sort(edge + 1, edge + 1 + m, cmp); st[edge[1].x] = 1; for (int i = 2; i <= m; ++i) { if (edge[i].x != edge[i - 1].x) en[edge[i - 1].x] = i - 1; st[edge[i].x] = i; } en[edge[m].x] = m; } //链表/链式前向星 int lin[MAXN + D], len = 0; struct node { int y, ne; } edge[MAXM + D]; inline void addedge(int x, int y) { edge[++len].y = y; edge[len].ne = lin[x]; lin[x] = len; } void init() { cin >> n >> m; for (int i = 1; i <= m; ++i) { int x, y; cin >> x >> y; addedge(x, y); } } //图的遍历 //DFS void dfs(int x) { vis[x] = true; for (int i = lin[x], y; i; i = edge[i].ne) if (!vis[y = edge[i].y]) dfs(y); } //DFS(邻接矩阵) void dfs(int x) { vis[x] = true; for (int i = 1; i <= n; ++i) if (a[x][i] && !vis[i]) dfs(i); } //BFS int head, tail, queue[MAXN + D]; void bfs(int s) { vis[s] = true; head = 0, tail = 1; queue[1] = s; while (head++ < tail) { int x = queue[head]; for (int i = lin[x], y; i; i = edge[i].ne) if (!vis[y = edge[i].y]) { queue[++tail] = y; vis[y] = true; } } } //BFS(邻接矩阵) int head, tail, queue[MAXN + D]; void bfs(int s) { vis[s] = true; head = 0, tail = 1; queue[1] = s; while (head++ < tail) { int x = queue[head]; for (int i = 1; i <= n; ++i) if (a[x][i] && !vis[i]) { queue[++tail] = i; vis[i] = true; } } } //最短路 //Floyd void Floyd() { for (int k = 1; k <= n; ++k) for (int i = 1; i <= n; ++i) for (int j = 1; j <= n; ++j) a[i][j] = std::min(a[i][j], a[i][k] + a[k][j]); } //Dijkstra #define INF 0x3f3f3f3f int dis[10010]; int vis[10010]; void Dijkstra(int s) { memset(vis, false, sizeof(vis)); for (int i = 1; i <= n; i++) dis[i] = a[s][i]; vis[s] = true; for (int i = 1; i < n; ++i) { int min = INF, x = 0; for (int i = 1; i <= n; ++i) if (!vis[i] && dis[i] < min) { min = dis[i]; x = i; } if (!x) return; vis[x] = true; for (int i = 1; i <= n; ++i) dis[i] = std::min(dis[i], dis[x] + a[x][i]); } } //Dijkstra_with_priority_queue using std::pair; using std::priority_queue; using std::vector; using std::greater; using std::make_pair; #define INF 0x3f3f3f3f typedef pair<int, int> pii; pirority_queue<pii, vector<pii>, greater<pii> > queue; void Dijkstra(int s) { memset(dis, 0x3f, sizeof(dis)); memset(vis, false, sizeof(vis)); dis[s] = 0; queue.push(make_pair(dis[s], 0)); while (!q.empty()) { pii tmp = q.top(); q.pop(); int x = tmp.second; if (vis[x]) continue; vis[x] = true; for (int i = lin[x], y; i; i = edge[i].ne) if (dis[y = edge[i].y] > dis[x] + edge[i].v) { dis[y] = dis[x] + edge[i].v; if (!vis[y]) q.push(make_pair(dis[y], y)); } } } //Bellman-Ford void Bellman_Ford(int s) { memset(dis, 0x3f, sizeof(dis)); dis[s] = 0; bool rel; for (int i = 1; i <= n; ++i) { rel = false; for (int j = 1; j <= len; ++j) if (dis[edge[j].y] > dis[edge[j].x] + edge[j].v) } } //SPFA int queue[10000010], head, tail; void SPFA(int s) { head = 0, tail = 1; memset(vis, false, sizeof(vis)); memset(dis, 0x3f, sizeof(dis)); dis[s] = 0; vis[s] = true; queue[1] = s; while (head++ < tail) { int x = queue[head]; vis[x] = false; for (int i = lin[x], y; i; i = edge[i].ne) if (dis[y = edge[i].y] > dis[x] + edge[i].v) { dis[y] = dis[x] + edge[i].v; if (!vis[y]) { vis[y] = true; queue[++tail] = y; } } } } //最小生成树 //Prim #define INF 0x3f3f3f3f int Prim() { memset(vis, false, sizeof(vis)); vis[1] = true; int sum = 0; for (int i = 1; i <= n; ++i) dis[i] = a[1][i]; for (int i = 1; i < n; ++i) { int min = INF, x = 0; for (int j = 1; j <= n; ++j) if (!vis[j] && dis[j] < min) { min = dis[j]; x = j; } vis[x] = true; sum += min; for (int j = 1; j <= n; ++j) dis[j] = std::min(dis[j], a[x][j]); } return sum; } //Kruskal struct node { int x, y, v; } edge[100010]; inline bool cmp(node x, node y) { return x.v <y.v; } int father[MAXN + D]; int getfather(int x) { return (father[x] == x) ? x : (father[x] = getfather(father[x])); } int Kruskal() { for (int i = 1; i <= n; ++i) father[i] = i; int sum = 0, cnt = 0; std::sort(edge + 1, edge + 1 + m, cmp); for (int i = 1; i <= m && cnt < n - 1; ++i) { int x = getfather(edge[i].x), y = getfather(edge[i].y); if (x != y) { ++cnt; sum += edge[i].v; father[x] = y; } } return sum; } //拓扑排序 int queue[MAXN + D], head, tail, in_degree[MAXN + D], ans[100][MAXN + D], tot = 0; void init() { cin >> n >> m; for (int i = 1; i <= m; ++i) { int x, y; cin >> x >> y; addedge(x, y); ++in_degree[y]; } } //BFS void bfs() { head = 0, tail = 0; for (int i = 1; i <= n; ++i) if (!in_degree[i]) queue[++tail] = y; while (head++ < tail) { int x = queue[head]; for (int i = lin[x],y; i; i = edge[i].ne) if (!(--in_degree[y = edge[i].y])) queue[++tail] = y; } } //DFS void dfs(int x, int dep) { queue[dep] = x; vis[x] = true; if (dep == n) { ++tot; for (int i = 1; i <= n; ++i) ans[tot][i] = queue[i]; vis[x] = false; } for (int i = lin[x]; i; i = edge[i].ne) --in_degree[edge[i].y]; for (int i = 1; i <= n; ++i) if (!vis[i] && !in_degree[i]) dfs(i, dep + 1); for (int i = lin[x]; i; i = edge[i].ne) ++in_degree[edge[i].y]; vis[x] = false; } //Tarjan //割点 int dfn[MAXN + D], low[MAXN + D], _clock = 0; bool iscut[MAXN + D] void tarjan(int x, int par = 0) { int child = 0; dfn[x] = low[x] = ++_clock; for (int i = lin[x], y; i; i = edge[i].ne) { if ((y = edge[i].y) == par) continue; if (!dfn[y]) { tarjan(y, x); if (low[y] < low[x]) low[x] = low[y]; else if (low[y] >= dfn[x]) ++child; } else if (dfn[y] < low[x]) low[x] = dfn[y]; } if (child >= 2 || (child == 1 && par)) iscut[x] = true; } int main() { for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i); } //点双连通分量 using std::vector; vector<int> bcc[MAXN + D]; int size[MAXN + D], dfn[MAXN + D], low[MAXN + D], _clock = 0, bel[MAXN + D], stack[MAXM + D], top = 0; void tarjan(int x, int par = 0) { int child = 0; dfn[x] = low[x] = ++_clock; for (int i = lin[x], y; i; i = edge[i].ne) { if ((y = edge[i].y) == par) continue; if (!dfn[y]) { stack[++top] = i; tarjan(y, x); if (low[y] < low[x]) low[x] = low[y]; else if (low[y] >= dfn[x]) { ++child; int k; ++tot; do { k = stack[top--]; if (bel[edge[k].x] != tot) { bel[edge[k].x] = tot; bcc[tot].push_back(edge[k].x); ++size[tot]; } if (bel[edge[k].y] != tot) { bel[edge[k].y] = tot; bcc[tot].push_back(edge[k].y); ++size[tot]; } } while (k != i); } } else if (dfn[y] < low[x]) { low[x] = dfn[y]; stack[++top] = i; } } if (child >= 2 || (par && child)) iscut[x] = true; } int main() { for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i); } //割边 int dfn[MAXN + D], low[MAXN + D], _clock = 0, rev[(MAXM << 1) + D]; bool isbridge[(MAXM << 1) + d]; void tarjan(int x, int par = 0) { dfn[x] = low[x] = ++_clock; for (int i = lin[x], y; i; i = edge[i].ne) { if (i == par) continue; if (!dfn[y = edge[i].y]) { tarjan(y, rev[i]); if (low[y] < low[x]) low[x] = low[y]; } else if (dfn[y] < low[x]) low[x] = dfn[y]; } if (dfn[x] == low[x]) isbridge[par] = isbridge[rev[par]] = true; } int main() { for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i); } //求割边后求边双连通分量 int tot = 0, bel[MAXN + D], size[MAXN + D]; void dfs(int i) { bel[i] = tot; ++size[tot]; for (int i = lin[x], y; i; i = edge[i].ne) { if (isbridge[i] || bel[y = edge[i].y]) continue; dfs(y); } } int main() { for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i); for (int i = 1; i <= n; ++i) if (!bel[i]) { ++tot; dfs(i); } } //连通分量 int dfn[MAXN + D], low[MAXN + D], _clock = 0, top = 0, stack[MAXN + D], bel[MAXN + D], size[MAXN + D], tot; bool vis[MAXN + D]; void tarjan(int x) { vis[x] = true; stack[++top] = x; dfn[x] = low[x] = ++_clock; for (int i = lin[x], y; i; i = edge[i].ne) { if (!dfn[y = edge[i].y]) { tarjan(y); if (low[y] < low[x]) low[x] = low[y]; } else if (vis[y] && dfn[y] < low[x]) low[x] = dfn[y]; } if (dfn[x] == low[x]) { int k; tot++; do { k = stack[top--]; vis[k] = false; ++size[tot]; bel[k] = tot; } while (k != x); } } int main() { for (int i = 1; i <= n; ++i) if (!dfn[i]) tarjan(i); } //DFS序列化 int st[MAXN + D], en[MAXN + D], _clock = 0; void dfs(int x, int par = 0) { st[x] = ++_clock; for (int i = lin[x], y; i; i = edge[i].ne) if ((y = edge[i].y) != par) dfs(y, x); en[x] = _clock; } //轻重链剖分 int st[MAXN + D], en[MAXN + D], _clock = 0, top[MAXN + D], size[MAXN + D], son[MAXN + D], father[MAXN + D], depth[MAXN + D]; void find_heavy_edge(int x, int par = 0) { father[x] = par; depth[x] = depth[par] + 1; size[x] = 1; int maxsize = 0; son[x] = 0; for (int i = lin[x], y; i; i = edge[i].y) { if ((y = edge[i].y) == par) continue; find_heavy_edge(y, x); if (size[y] > maxsize) { maxsize = size[y]; son[x] = y; } size[x] += size[y]; } } void connect_heavy_edge(int x, int par) { st[x] = ++_clock; top[x] = par; if (son[x]) connect_heavy_edge(son[x], par); for (int i = lin[x], y; i; i = edge[i].ne) { y = edge[i].y; if (y == par || y == son[x]) continue; connect_heavy_edge(y, y); } en[x] = _clock; } int main() { find_heavy_edge(1); connect_heavy_edge(1, 1); } //LCA //树链剖分 int LCA(int u, int v) { while (top[u] != top[v]) { if (depth[top[u]] < depth[top[v]]) std::swap(u, v); u = father[top[u]]; } if (depth[u] > depth[v]) std::swap(u, v); return v; } //倍增法 int father[MAXN + D][20], depth[MAXN + D], M; void dfs(int x) { for (int i = 1; (1 << i) <= n && father[x][i - 1]; ++i) father[x][i] = father[father[x][i - 1]][i - 1]; for (int i = lin[x], y; i; i = edge[i].ne) { if ((y = edge[i].y) == father[x][0]) continue; father[y][0] = x; dfs(y); } } int LCA(int u, int v) { if (depth[u] < depth[v]) std::swap(u, v); for (int i = 0; depth[u] != depth[v]; ++i) if ((1 << i) & (depth[u] - depth[v])) u = father[u][i]; if (u == v) return u; for (int i = M; i >= 0; --i) if (father[u][i] != father[v][i]) { u = father[u][i]; v = father[v][i]; } return father[u][0]; } int main() { for (M = 0; (1 << M) <= n; ++M); --M; dfs(1); } //tarjan离线法 struct query { int y, ne, id; } query[MAXM + D]; int len_query = 0, lin_query[MAXN + D], father[MAXN + D], ans[MAXM + D]; bool vis[MAXN + D]; inline void addquery(int x, int y, int id) { query[++len_query].y = y; query[len_query].ne = lin_query[x]; lin_query[x] = len_query; query[len_query].id = id; } int getfather(int x) { return (father[x] == x) ? x : (father[x] = getfather(father[x])); } void tarjan(int x, int par = 0) { for (int i = lin[x], y; i; i = edge[i].ne) { if ((y = edge[i].y) == par) continue; tarjan(y, x); father[y] = x; vis[y] = true; } for (int i = lin_query[x], y; i; i = query[i].ne) { if (!vis[y = query[i].y]) continue; ans[query[i].id] = getfather(y); } } int main() { for (int i = 1; i <= n; ++i) father[i] = i; tarjan(1); } //点分治 int size[MAXN + D], root, sum = 0, maxsize[MAXN + D]; bool vis[MAXN + D]; void getroot(int x, int par) { size[x] = 1; maxsize[x] = 0; for (int i = lin[x], y; i; i = edge[i].ne) { y = edge[i].y; if (y == par || vis[y]) continue; getroot(y, x); maxsize[x] = std::max(maxsize[x], size[y]); size[x] += size[y]; } maxsize[x] = std::max(maxsize[x], sum - maxsize[x]); if (maxsize[x] < maxsize[root]) root = x; } void cal(int x, int par) { //计算当前点贡献 for (int i = lin[x], y; i; i = edge[i].ne) { y = edge[i].y; if (vis[y] || y == par) continue; cal(y, x); } } void add(int x, int par, bool opt) { if (opt) { //将当前点加入到计算的点中 } else { //将当前点从已计算的点集删除 } for (int i = lin[x], y; i; i = edge[i].ne) { y = edge[i].y; if (vis[y] || y == par) continue; add(y, x, opt); } } void solve(int x) { getroot(x); vis[x] = true; for (int i = lin[x], y; i; i = edge[i].ne) { y = edge[i].y; if (vis[y]) continue; cal(y, x); add(y, x, true); } for (int i = lin[x], y; i; i = edge[i].ne) { y = edge[i].y; if (vis[y]) continue; add(y, x, false); } for (int i = lin[x], y; i; i = edge[i].ne) { y = edge[i].y; if (vis[y]) continue; sum = size[y]; root = 0; getroot(y, x); solve(root); } }
大量图结构模板,可能会有帮助...