图论模板

该模板基于刘汝佳算法竞赛入门经典--训练指南

该模板部分参考自《ACM国际大学生程序设计竞赛--算法与实现》

图论常用模板

转载请注明:转自http://blog.csdn.net/a15129395718

新的独立博客,欢迎访问: http://zihengoi.cn


[cpp]  view plain  copy
  1. #include <bits/stdc++.h>  
  2. using namespace std;  
  3.   
  4. typedef long long LL;  
  5.   
  6. const int MAXN = 1000;  
  7. const int INF = 0x3f3f3f3f;  
  8.   
  9. //染色  
  10. //判断结点u所在的连通分量是否为二分图  
  11. //未染色结点值为0, 已染色结点值为1/2.  
  12. int color[MAXN];  
  13. bool bipartite(int u) {  
  14.     for(int i = 0; i < G[u].size(); i++){  
  15.         int v = G[u][i];                      //枚举每条边(u, v)  
  16.         if(color[v] == color[u]) return false;//结点v已着色,且和结点u的颜色冲突  
  17.         if(!color[v]) {  
  18.             color[v] = 3 - color[u];          //给结点v着与结点u相反的颜色  
  19.             if(!bipartite(v)) return false;  
  20.         }  
  21.     }  
  22.     return true;  
  23. }  
  24.   
  25. //无向图求桥求割  
  26. struct Edge{  
  27.     int v, w;  
  28.     bool cut;  
  29.     Edge(int v, int w, int cnt = false) : v(v), w(w), cut(cut) {}  
  30. };  
  31. bool iscut[MAXN];  
  32. vector<Edge> G[MAXN];  
  33. int dfs_clock, low[MAXN], pre[MAXN];  
  34.   
  35. int dfs(int u, int fa) {    //u在DFS树中的父节点是fa  
  36.     int lowu = pre[u] = ++dfs_clock;  
  37.     bool flag = false;  
  38.     int child = 0;          //子节点数目  
  39.     for(int i = 0; i < G[u].size(); i++) {  
  40.         int v = G[u][i].v;  
  41.         if(!pre[v]) {  
  42.             child++;  
  43.             int lowv = dfs(v, u);  
  44.             lowu = min(lowu, lowv);         //用后代的low函数更新u的low函数  
  45.             if(lowv >= pre[u]) {  
  46.                 if(lowv > pre[u]) G[u][i].cut = true;  
  47.                 iscut[u] = true;  
  48.             }  
  49.         } else if(v == fa) {  
  50.             if(flag) lowu = min(lowu, pre[v]);  
  51.             flag = true;  
  52.         } else lowu = min(lowu, pre[v]);       //用反向边更新u的low函数  
  53.     }  
  54.     if(fa < 0 && child == 1) iscut[u] = 0;  
  55.     low[u] = lowu;  
  56.     return lowu;  
  57. }  
  58.   
  59. //有向图的强连通分量  
  60. vector<int> G[MAXN];  
  61. int pre[MAXN], low[MAXN], sccno[MAXN], dfs_clock, scc_cnt;  
  62. stack<int> S;  
  63.   
  64. void Tarjan(int u) {  
  65.     pre[u] = low[u] = ++dfs_clock;  
  66.     S.push(u);  
  67.     for(int i = 0; i < G[u].size(); i++) {  
  68.         int v = G[u][i];  
  69.         if(!pre[v]) {  
  70.             Tarjan(v);  
  71.             low[u] = min(low[u], low[v]);  
  72.         } else if(!sccno[v]) low[u] = min(low[u], pre[v]);  
  73.     }  
  74.     if(low[u] == pre[u]) {  
  75.         scc_cnt++;  
  76.         while(true) {  
  77.             int x = S.top();  
  78.             S.pop();  
  79.             sccno[x] = scc_cnt;  
  80.             if(x == u) break;  
  81.         }  
  82.     }  
  83. }  
  84.   
  85. void find_scc(int n) {  
  86.     dfs_clock = scc_cnt = 0;  
  87.     memset(sccno, 0 , sizeof(sccno));  
  88.     memset(pre, 0, sizeof(pre));  
  89.     for(int i = 0; i < n; i++)  
  90.         if(!pre[i]) Tarjan(i);  
  91. }  
  92.   
  93. //2-SAT  
  94. struct TwoSAT {  
  95.     stack<int> S;  
  96.     vector<int> G[MAXN*2];  
  97.     int n, dfs_clock, scc_cnt;  
  98.     int pre[MAXN*2], low[MAXN*2], sccno[MAXN*2];  
  99.   
  100.     void init(int n) {  
  101.         this->n = n;  
  102.         for(int i = 0; i < MAXN*2; i++) g[i].clear();  
  103.     }  
  104.   
  105.     void addEdge(int x, int xv, int y, int yv) {  
  106.         x = x*2 + xv;  
  107.         y = y*2 + yv;  
  108.         g[x].push_back(y);  
  109.     }  
  110.   
  111.     void dfs(int u) {  
  112.         pre[u] = low[u] = ++dfs_clock;  
  113.         S.push(u);  
  114.         for(int i = 0; i < g[u].size(); i++) {  
  115.             int v = g[u][i];  
  116.             if(!pre[v]) {  
  117.                 dfs(v);  
  118.                 low[u] = min(low[u], low[v]);  
  119.             } else if(!sccno[v]) low[u] = min(low[u], pre[v]);  
  120.         }  
  121.         if(low[u] == pre[u]) {  
  122.             scc_cnt++;  
  123.             while(true) {  
  124.                 int x = S.top();  
  125.                 S.pop();  
  126.                 sccno[x] = scc_cnt;  
  127.                 if(x == u) break;  
  128.             }  
  129.         }  
  130.     }  
  131.   
  132.     void find_scc() {  
  133.         dfs_clock = scc_cnt = 0;  
  134.         memset(pre, 0, sizeof pre);  
  135.         memset(sccno, 0, sizeof sccno);  
  136.         for(int i = 0; i < n*2; i++) if(!pre[i]) dfs(i);  
  137.     }  
  138.   
  139.     bool solve() {  
  140.         find_scc();  
  141.         for(int i = 0; i < n; i++)  
  142.             if(sccno[i*2] == sccno[i*2+1]) return false;  
  143.         return true;  
  144.     }  
  145. };  
  146.   
  147.   
  148. //Dijkstra(O(n2))  
  149. bool vis[MAXN];  
  150. int n, d[MAXN];  
  151. int w[MAXN][MAXN];  
  152. int fa[MAXN];  
  153. void Dijkstra(int s) {  
  154.     memset(vis, 0, sizeof(vis));  
  155.     for(int i = 0; i < n; i++) d[i] == (i == s ? 0 : INF);  
  156.     for(int i = 0; i < n; i++) {  
  157.         int x, m = INF;  
  158.         for(int y = 0; y < n; y++) if(!vis[y] && d[y] <= m) m = d[x=y];  
  159.         vis[x] = true;  
  160.         for(int y = 0; y < n; y++)  
  161.         if(d[y] > d[x] + w[x][y]) {  
  162.             d[y] = d[x] + w[x][y];  
  163.             fa[y] = x;  
  164.         }  
  165.     }  
  166. }  
  167.   
  168. //Dijkstra+HeapNode(O(m*lgn))  
  169. struct Edge {  
  170.     int u, v, w;  
  171.     Edge() {}  
  172.     Edge(int u, int v, int w) : u(u), v(v), w(w) {}  
  173. };  
  174. struct HeapNode {  
  175.     int d, u;  
  176.     HeapNode() {}  
  177.     HeapNode(int d, int u) : d(d), u(u) {}  
  178.   
  179.     bool operator < (const HeapNode& rhs) const {  
  180.         return d > rhs.d;  
  181.     }  
  182. };  
  183. struct Dijkstra {  
  184.     int n, m;  
  185.     vector<Edge> edges;  
  186.     vector<int> G[MAXN];  
  187.     bool done[MAXN];  
  188.     int d[MAXN];  
  189.     int p[MAXN];  
  190.   
  191.     void init(int n) {  
  192.         this -> n = n;  
  193.         for(int i = 0; i <= n; i++) G[i].clear();  
  194.         edges.clear();  
  195.     }  
  196.   
  197.     void addEdge(int u, int v, int w) {  
  198.         edges.push_back(Edge(u, v, w));  
  199.         G[u].push_back(edges.size()-1);  
  200.     }  
  201.   
  202.     void dijkstra(int s) {  
  203.         priority_queue<HeapNode> Q;  
  204.         for(int i = 0; i <= n; i++) d[i] = INF;  
  205.         d[s] = 0;  
  206.         memset(done, 0, sizeof(done));  
  207.         Q.push(HeapNode(0,s));  
  208.         while(!Q.empty()) {  
  209.             HeapNode x = Q.top();  
  210.             Q.pop();  
  211.             int u = x.u;  
  212.             if(done[u]) continue;  
  213.             done[u] = true;  
  214.             for(int i = 0; i < G[u].size(); i++) {  
  215.                 Edge& e = edges[G[u][i]];  
  216.                 if(d[e.v] > d[u] + e.w) {  
  217.                     d[e.v] = d[u] + e.w;  
  218.                     p[e.v] = G[u][i];  
  219.                     Q.push(HeapNode(d[e.v], e.v));  
  220.                 }  
  221.             }  
  222.         }  
  223.     }  
  224. };  
  225.   
  226. //Floyed算法  
  227. void Floyed() {  
  228.     for(int k = 0; k < n; k++)  
  229.         for(int i = 0; i < n; i++)  
  230.             for(int j = 0; j < n; j++)  
  231.                 d[i][j] = min(d[i][j], d[i][k]+d[k][j]);  
  232. }  
  233.   
  234. //SPFA(BFS)  
  235. void SPFA(int s) {  
  236.     queue<int> Q;  
  237.     d[s] = 0;  
  238.     Q.push(s);  
  239.     while(!Q.empty()) {  
  240.         int u = Q.front();  
  241.         Q.pop();  
  242.         for(int i = head[u]; i != -1; i = edge[i].next) {  
  243.             int v = edge[i].to, w = edge[i].w;  
  244.             if(d[v] > d[u] + w) {  
  245.                 d[v] = d[u] + w;  
  246.                 Q.push(v);  
  247.             }  
  248.         }  
  249.     }  
  250. }  
  251.   
  252. //SPFA(DFS)  
  253. bool spfa(int u) {  
  254.     vis[u] = 1;  
  255.     for(int v = 1; v <= n; v++) {  
  256.         if(mp[u][v] && d[u] + e[v] > d[v] && d[u] + e[v] > 0) {  
  257.             d[v] = d[u] + e[v];  
  258.             if(!vis[v]) {  
  259.                 if(spfa(v)) return true;  
  260.             } else return reach[v][n];  
  261.         }  
  262.     }  
  263.     vis[u] = 0;  
  264.     return d[n] > 0;  
  265. }  
  266.   
  267. //两个条件下的最短路 HDU1245  
  268. void SPFA() {  
  269.     for(int i = 0; i < MAXN; i++) dis[i] = step[i] = INF, vis[i] = 0;  
  270.     queue<int> Q;  
  271.     dis[0] = step[0] = 0, vis[0] = 1;  
  272.     Q.push(0);  
  273.     while(!Q.empty()) {  
  274.         int u = Q.front();  
  275.         Q.pop();  
  276.         vis[u] = 0;  
  277.         for(int j = 0; j < G[u].size(); j++) {  
  278.             int v = G[u][j].v;  
  279.             double len = G[u][j].dist;  
  280.             if(abs(dis[v]-dis[u]-len) <= EPS) {  
  281.                 if(step[v] > step[u]+1)  
  282.                     step[v] = step[u]+1;  
  283.             } else if(dis[v] >= dis[u]+len) {  
  284.                 dis[v] = dis[u]+len;  
  285.                 step[v] = step[u]+1;  
  286.                 if(!vis[v]) {  
  287.                     vis[v]=1;  
  288.                     Q.push(v);  
  289.                 }  
  290.             }  
  291.         }  
  292.     }  
  293. }  
  294.   
  295. //Prim  
  296. int Prim() {  
  297.     int s = 0, cnt = 1, ans = 0, pos, low[MAXN];  
  298.     bool vis[MAXN];  
  299.     for(int i = 0; i <= n; i++) low[i] = INF, vis[i] = false;  
  300.     vis[s] = true;  
  301.     while(true) {  
  302.         if(cnt == n) break;  
  303.         int mn = INF;  
  304.         for(int j = 1; j < n; j++) {  
  305.             if(!vis[j] && low[j] > dist[s][j]) low[j] = dist[s][j];  
  306.             if(!vis[j] && mn > low[j]) mn = low[pos=j];  
  307.         }  
  308.         vis[s=pos] = true;  
  309.         ans += mn;  
  310.         cnt++;  
  311.     }  
  312.     return ans;  
  313. }  
  314.   
  315. //Kruskal  
  316. void Kruskal() {  
  317.     ans = 0;  
  318.     for(int i = 0; i <= n; i++) fa[i] = i;  
  319.     for(unsigned i = 0; i < G.size(); i++) {  
  320.         int u = G[i].u, v = G[i].v, w = G[i].w;  
  321.         int x = Find(u), y = Find(v);  
  322.         if(x != y) {  
  323.             ans += w;  
  324.             fa[y] = x;  
  325.         }  
  326.     }  
  327.     printf("%d\n", ans);  
  328. }  
  329.   
  330. //匈牙利算法(二分图最大匹配)O(|E|*sqrt(|V|))  
  331. bool vis[MAXN];  
  332. vector<int> G[MAXN];  
  333. int n, m, k, head[MAXN];  
  334.   
  335. bool match(int x) {  
  336.     for(unsigned i = 0; i < G[x].size(); i++) {  
  337.         if(!vis[G[x][i]]) {  
  338.             vis[G[x][i]] = true;  
  339.             if(head[G[x][i]] == -1 || match(head[G[x][i]])) {  
  340.                 head[G[x][i]] = x;  
  341.                 return true;  
  342.             }  
  343.         }  
  344.     }  
  345.     return false;  
  346. }  
  347.   
  348. int hungary() {  
  349.     int res = 0;  
  350.     memset(head, -1, sizeof(head));  
  351.     for(int i = 0; i < n; i++) {  
  352.         memset(vis, 0, sizeof(vis));  
  353.         if(match(i)) res++;  
  354.     }  
  355.     return res;  
  356. }  
  357.   
  358.   
  359. //最小树形图  
  360. /******************************************************************** 
  361. * 给定一个有向图, 求以某个给定顶点为根的有向生成树(也就是说沿着 
  362.   这N-1条边可以从根走到任意点),使权和最小。 
  363. * 判断是否存在最小树形图,以根为起点DFS一遍即可。 
  364. *********************************************************************/  
  365. double G[MAXN][MAXN];  
  366. int used[MAXN], pass[MAXN], eg[MAXN], more, Queue[MAXN], n, m;  
  367.   
  368. inline void combine(int id, double& sum) {  
  369.     int tot = 0, from;  
  370.     for(; id != 0 && !pass[id]; id = eg[id]) {  
  371.         Queue[tot++] = id;  
  372.         pass[id] = 1;  
  373.     }  
  374.     for(from = 0; from < tot && Queue[from] != id; ++from);  
  375.     if(from == tot) return;  
  376.     more = 1;  
  377.     for(int i = from; i < tot; i++) {  
  378.         sum += G[eg[Queue[i]]][Queue[i]];  
  379.         if(i != from) {  
  380.             used[Queue[i]] = 1;  
  381.             for(int j = 1; j <= n; j++) if(!used[j]) {  
  382.                     if(G[Queue[i]][j] < G[id][j])  
  383.                         G[id][j] = G[Queue[i]][j];  
  384.                 }  
  385.         }  
  386.     }  
  387.     for(int i = 1; i <= n; ++i) if(!used[i] && i != id) {  
  388.             for(int j = from; j < tot; ++j) {  
  389.                 int k = Queue[j];  
  390.                 if(G[i][id] > G[i][k] - G[eg[k]][k])  
  391.                     G[i][id] = G[i][k] - G[eg[k]][k];  
  392.             }  
  393.         }  
  394. }  
  395.   
  396. inline double mdst(int root) {  
  397.     double sum = 0;  
  398.     memset(used, 0, sizeof(used));  
  399.     for(more = 1; more; ) {  
  400.         more = 0;  
  401.         memset(eg, 0, sizeof(eg));  
  402.         for(int i = 1; i <= n; ++i)  
  403.     }  
  404. }  
  405.   
  406. //最大流Dinic算法(O(N^2*M))  
  407. struct Edge{  
  408.     int from, to, cap, flow;  
  409.     Edge() {}  
  410.     Edge(int from, int to, int cap, int flow) : from(from), to(to), cap(cap), flow(flow) {}  
  411. };  
  412.   
  413. struct Dinic {  
  414.     int n, m, s, t;  
  415.     vector<Edge> edges;  
  416.     vector<int> G[MAXN];  
  417.     bool vis[MAXN];  
  418.     int d[MAXN];  
  419.     int cur[MAXN];  
  420.   
  421.   
  422.     void AddEdge(int from, int to, int cap) {  
  423. //        cout << from << "<=====> " << to <<  "   "<< cap << endl;  
  424.         edges.push_back(Edge(from, to, cap, 0));  
  425.         edges.push_back(Edge(to, from, 0, 0));  
  426.         m = edges.size();  
  427.         G[from].push_back(m-2);  
  428.         G[to].push_back(m-1);  
  429.     }  
  430.   
  431.     bool BFS() {  
  432.         memset(vis, 0, sizeof(vis));  
  433.         queue<int> Q;  
  434.         Q.push(s);  
  435.         d[s] = 0;  
  436.         vis[s] = 1;  
  437.         while(!Q.empty()) {  
  438.             int x = Q.front();  
  439.             Q.pop();  
  440.             for(int i = 0; i < G[x].size(); i++) {  
  441.                 Edge& e = edges[G[x][i]];  
  442.                 if(!vis[e.to] && e.cap > e.flow) {  
  443.                     vis[e.to] = 1;  
  444.                     d[e.to] = d[x] + 1;  
  445.                     Q.push(e.to);  
  446.                 }  
  447.             }  
  448.         }  
  449.         return vis[t];  
  450.     }  
  451.   
  452.     int DFS(int x, int a) {  
  453.         if(x == t || a == 0) return a;  
  454.         int flow = 0, f;  
  455.         for(int& i = cur[x]; i < G[x].size(); i++) {  
  456.             Edge& e = edges[G[x][i]];  
  457.             if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0 ) {  
  458.                 e.flow += f;  
  459.                 edges[G[x][i]^1].flow -= f;  
  460.                 flow += f;  
  461.                 a -= f;  
  462.                 if(a == 0) break;  
  463.             }  
  464.         }  
  465.         return flow;  
  466.     }  
  467.   
  468.     int MaxFlow(int s, int t) {  
  469.         this-> s = s;  
  470.         this-> t = t;  
  471.         int flow = 0;  
  472.         while(BFS()) {  
  473.             memset(cur, 0, sizeof(cur));  
  474.             flow += DFS(s, INF);  
  475.         }  
  476. //        cout << flow << endl;  
  477.         return flow;  
  478.     }  
  479. };  
  480.   
  481. //最小费用最大流  
  482. //是否在队列中  
  483. bool vis[MAXN];  
  484. //a可改尽量 p上一条弧 d费用  
  485. int a[MAXN], p[MAXN], d[MAXN];  
  486. //最大流, 最小费用  
  487. int flow, cost, n, m;  
  488.   
  489. struct Edge {  
  490.     int from, to, cap, flow, cost;  
  491.     Edge() {}  
  492.     Edge(int from, int to, int cap, int flow, int cost) : from(from), to(to), cap(cap), flow(flow), cost(cost) {}  
  493. };  
  494.   
  495. vector<Edge> edges;  
  496. vector<int> G[MAXN];  
  497.   
  498. inline void init() {  
  499.     flow = cost = 0;  
  500.     for(int i = 0; i <= n; i++) G[i].clear();  
  501.     edges.clear();  
  502. }  
  503.   
  504. void addEdge(int from, int to, int cap, int cost) {  
  505.     edges.push_back(Edge(from, to, cap, 0, cost));  
  506.     edges.push_back(Edge(to, from, 0, 0, -cost));  
  507.     int m = edges.size();  
  508.     G[from].push_back(m-2);  
  509.     G[to].push_back(m-1);  
  510. }  
  511.   
  512. bool spfa(int s, int t, int& flow, int& cost) {  
  513.     for(int i = 0; i <= n; i++) d[i] = INF;  
  514.     memset(vis, falsesizeof(vis));  
  515.     d[s] = 0, vis[s] = true, p[s] = 0, a[s] = INF;  
  516.     queue<int> Q;  
  517.     Q.push(s);  
  518.     while(!Q.empty()) {  
  519.         int u = Q.front(); Q.pop();  
  520.         vis[u] = false;  
  521.         for(int i = 0; i < G[u].size(); i++) {  
  522.             Edge& e = edges[G[u][i]];  
  523.             if(e.cap > e.flow && d[e.to] > d[u] + e.cost) {  
  524.                 d[e.to] = d[u] + e.cost;  
  525.                 p[e.to] = G[u][i];  
  526.                 a[e.to] = min(a[u], e.cap - e.flow);  
  527.                 if(!vis[e.to]) Q.push(e.to), vis[e.to] = 1;  
  528.             }  
  529.         }  
  530.     }  
  531.     if(d[t] == INF) return false;  
  532.     flow += a[t], cost += d[t] * a[t];  
  533.     int u = t;  
  534.     while(u != s) {  
  535.         edges[p[u]].flow += a[t];  
  536.         edges[p[u]^1].flow -= a[t];  
  537.         u = edges[p[u]].from;  
  538.     }  
  539.     return true;  
  540. }  
  541.   
  542. int main() {  
  543.     return 0;  
  544. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值