所有模板都是从0开始计数,如果题目输入从1开始,需要自己处理
堆优化的Dijkstra
const int MAXV = 0; struct Edge { int from, to, dist; }; struct HeapNode { int d, u; bool operator < (const HeapNode& rhs) const { return d > rhs.d; } }; struct Dijkstra { int n, m; //n:点数 m:临时变量 vector<Edge> edges; //存储所有的边 vector<int> G[MAXV];//每个点的所有相邻边序号 bool done[MAXV]; // 是否已永久标号 int d[MAXV]; // s起点到各个点的距离 int p[MAXV]; // 最短路树中的上一条边序号 void init(int n) { this->n = n; for(int i = 0; i < n; i++) G[i].clear(); edges.clear(); } void AddEdge(int from, int to, int dist) { edges.push_back((Edge) { from, to, dist }); m = edges.size(); G[from].push_back(m - 1); } void dijkstra(int s) { priority_queue<HeapNode> Q; for(int i = 0; i < n; i++) d[i] = INF; d[s] = 0; memset(done, 0, sizeof(done)); Q.push((HeapNode) { 0, s }); while(!Q.empty()) { HeapNode x = Q.top(); Q.pop(); int u = x.u; if(done[u]) continue; done[u] = true; for(int i = 0; i < G[u].size(); i++) { Edge& e = edges[G[u][i]]; if(d[e.to] > d[u] + e.dist) { d[e.to] = d[u] + e.dist; p[e.to] = G[u][i]; Q.push((HeapNode) { d[e.to], e.to }); } } } } };
//使用时只更新G完成构图 //bcc_cnt从1开始计数 //pre[]表示点在DFS树中的先序时间戳 //iscut[]表示点是否为割点 //bccno[]表示点所在的双连通分量编号 //bcc_cnt表示双连通分量个数 //vector<int> G保存每个点相邻的下一个点序号 //vector<int> bcc保存每个双连通分量的点集,算法运行过程动态清空 //stack<Edge> S是算法用到的栈 const int MAXV = 0; struct Edge { int u, v; }; int pre[MAXV], iscut[MAXV], bccno[MAXV], dfs_clock, bcc_cnt; // 割顶的bccno无意义 vector<int> G[MAXV], bcc[MAXV]; stack<Edge> S; void init(int n) { REP(i, n) G[i].clear(); } int dfs(int u, int fa) { int lowu = pre[u] = ++dfs_clock; int child = 0; for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; Edge e = (Edge){u, v}; if(!pre[v]) // 没有访问过v { S.push(e); child++; int lowv = dfs(v, u); lowu = min(lowu, lowv); // 用后代的low函数更新自己 if(lowv >= pre[u]) { iscut[u] = true; bcc_cnt++; bcc[bcc_cnt].clear(); for(;;) { Edge x = S.top(); S.pop(); if(bccno[x.u] != bcc_cnt) { bcc[bcc_cnt].push_back(x.u); bccno[x.u] = bcc_cnt; } if(bccno[x.v] != bcc_cnt) { bcc[bcc_cnt].push_back(x.v); bccno[x.v] = bcc_cnt; } if(x.u == u && x.v == v) break; } } } else if(pre[v] < pre[u] && v != fa) { S.push(e); lowu = min(lowu, pre[v]); // 用反向边更新自己 } } if(fa < 0 && child == 1) iscut[u] = 0; return lowu; } void find_bcc(int n) { // 调用结束后S保证为空,所以不用清空 memset(pre, 0, sizeof(pre)); memset(iscut, 0, sizeof(iscut)); memset(bccno, 0, sizeof(bccno)); dfs_clock = bcc_cnt = 0; for(int i = 0; i < n; i++) if(!pre[i]) dfs(i, -1); };
二分图判断
//color[]表示每个点的颜色:0->未涂色,1和2表示涂的色 const int MAXV = 0; int color[MAXV]; void init(int n) { REP(i, n) color[i] = 0; } bool bipartite(int u) { REP(i, G[u].size()) { int v = G[u][i]; if (color[v] == color[u]) return false; if (!color[v]) { color[v] = 3 - color[u]; if (!bipartite(v, b)) return false; } } return true; }
有向图的强连通分量
//使用时只更新G完成构图 //scc_cnt从1开始计数 //pre[]表示点在DFS树中的先序时间戳 //lowlink[]表示当前点和后代能追溯到的最早祖先的pre值 //sccno[]表示点所在的双连通分量编号 //vector<int> G保存每个点相邻的下一个点序号 //stack<Edge> S是算法用到的栈 const int MAXV = 0; vector<int> G[MAXV]; int pre[MAXV], lowlink[MAXV], sccno[MAXV], dfs_clock, scc_cnt; stack<int> S; void init(int n) { REP(i, n) G[i].clear(); } void dfs(int u) { pre[u] = lowlink[u] = ++dfs_clock; S.push(u); for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(!pre[v]) { dfs(v); lowlink[u] = min(lowlink[u], lowlink[v]); } else if(!sccno[v]) { lowlink[u] = min(lowlink[u], pre[v]); } } if(lowlink[u] == pre[u]) { scc_cnt++; for(;;) { int x = S.top(); S.pop(); sccno[x] = scc_cnt; if(x == u) break; } } } void find_scc(int n) { dfs_clock = scc_cnt = 0; memset(sccno, 0, sizeof(sccno)); memset(pre, 0, sizeof(pre)); for(int i = 0; i < n; i++) if(!pre[i]) dfs(i); };
//如果标记了2i表示假,标记了2i+1表示真 //调用solve函数获得整个图的值 //n是点的数量 //vector<int> G存储下一个点的序号 //mark[2 * i] = true表示i点为假,mark[2 * i + 1] = true表示i点为真 //S[]是算法使用的逻辑栈,c是栈计数值 const int MAXV = 2100; struct TwoSAT { int n; vector<int> G[MAXV*2]; bool mark[MAXV*2]; int S[MAXV*2], c; void init(int n) { this->n = n; for (int i = 0; i < n*2; i++) G[i].clear(); memset(mark, 0, sizeof(mark)); } bool dfs(int x) { if (mark[x^1]) return false; if (mark[x]) return true; mark[x] = true; S[c++] = x; for (int i = 0; i < G[x].size(); i++) if (!dfs(G[x][i])) return false; return true; } // x = xval or y = yval void add_clause(int x, int xval, int y, int yval) { x = x * 2 + xval; y = y * 2 + yval; G[x^1].push_back(y); G[y^1].push_back(x); } bool solve() { for(int i = 0; i < n*2; i += 2) if(!mark[i] && !mark[i+1]) { c = 0; if(!dfs(i)) { while(c > 0) mark[S[--c]] = false; if(!dfs(i+1)) return false; } } return true; } };
原文:http://blog.csdn.net/wty__/article/details/22379143