图论二
0、目錄
最短路、最小生成樹、LCA
(參考自白皮)
1、最短路
1.1、Floyd
for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){mat[i][j]=INF;if(i==j) mat[i][j]=0;pre[i][j]=i; } }for(int k=1;k<=n;k++){for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);}} }vector<int> path; path.push_back(t); while(pre[s][t]!=s) {path.pb(pre[s][t]);t=pre[s][t]; } path.push_back(s); reverse(path.begin(),path.end());1.2、Dijkstra
struct Edge{int u,v,d; };struct HeapNode{int d,u;HeapNode(int d,int u):d(d),u(u){}bool operator < (const HeapNode& tmp) const {return d>tmp.d;} };struct Dijkstra{int n,m;vector<Edge> egs;vector<int> G[maxn];bool done[maxn];int d[maxn];int p[maxn];void init(int n){this->n=n;for(int i=0;i<n;i++) G[i].clear();egs.clear(); }void addEdge(int u,int v,int d){egs.push_back(Edge(u,v,d));m=egs.size();G[u].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]=1;for(int i=0;i<G[u].size();i++){Edge& e=egs[G[u][i]];if(d[e.v]>d[u]+e.d){d[e.v]=d[u]+e.d;p[e.v]=G[u][i];Q.push(HeapNode(d[e.v],e.v));}}}} };1.3、Spfa
struct Spfa{int n,m;vector<Edge> egs;vector<int> G[maxn];bool inq[maxn];int d[maxn];int p[maxn];int cnt[maxn];void init(int n){this->n=n;for(int i=0;i<n;i++) G[i].clear();egs.clear(); }void addEdge(int u,int v,int d){egs.push_back(Edge(u,v,d));m=egs.size();G[u].push_back(m-1);}bool spfa(int s){queue<int> Q;memset(inq,0,sizeof(inq));memset(cnt,0,sizeof(cnt));for(int i=0;i<n;i++) d[i]=INF;d[s]=0,inq[s]=true,Q.push(s);while(!Q.empty()){int u=Q.front(); Q.pop();inq[u]=false;for(int i=0;i<G[u].size();i++){Edge& e=egs[G[u][i]];if(d[e.v]>d[u]+e.d){d[e.v]=d[u]+e.d;p[e.v]=G[u][i];if(!inq[e.v]){Q.push(e.v),inq[e.v]=true;if(++cnt[e.v]>n) return false;}}}}return true;} };2、最小生成樹
2.0、兩個性質
- 切割性質:假定所有的邊權均不相等。設S為既非空集也非全集的V的子集,邊e是滿足一個端點在S內,另一個端點不在S內的所有邊中權值最小的一個,則圖G的所有最小生成樹均包含e。
- 回路性質:假定所有的邊權均不相同。設C是圖G中的任意回路,邊e是C上權值最大的邊,則圖G的所有最小生成樹均不包含e。
2.1、無相圖
/*kruskal*/ int fa[maxn]; int find(int x){ return fa[x]=fa[x]==x?x:find(fa[x]); }int kruskal(){int ret=0;for(int i=0;i<maxn;i++) fa[i]=i;sort(egs,egs+m);for(int i=0;i<m;i++){Edge& e=egs[i];int pu=find(e.u);int pv=find(e.v);if(pu!=pv){fa[pv]=pu;ret+=e.w; }}return ret; }2.2、有向圖(最小樹形圖)
LL in[maxn]; int id[maxn], vis[maxn], pre[maxn]; LL Directed_MST(int rt) {LL ret = 0;while (1) {//求最小入度邊for (int i = 0; i < n; i++) in[i] = INF;for (int i = 0; i < m; i++) {Edge& e = egs[i];if (e.w < in[e.v] && e.u != e.v) {in[e.v] = e.w;pre[e.v] = e.u;}}for (int i = 0; i < n; i++) {if (i!=rt&&in[i] == INF) return -1;}int tot = 0;memset(id, -1, sizeof(id));memset(vis, -1, sizeof(vis));in[rt] = 0;//找環,縮點for (int i = 0; i < n; i++) {ret += in[i];int v = i;while (vis[v] != i&&id[v] == -1 && v != rt) {vis[v] = i;v = pre[v];}if (id[v] == -1 && v != rt) {for (int u = pre[v]; u != v; u = pre[u]) {id[u] = tot;}id[v] = tot++;}}//沒有環if (tot == 0) break;for (int i = 0; i < n; i++) {if (id[i] == -1) id[i] = tot++;}//更新到環的距離for (int i = 0; i < m; i++) {Edge& e = egs[i];int v = e.v;//這個v要留下來!e.u = id[e.u],e.v = id[e.v];if (e.u != e.v) {e.w -= in[v];}}n = tot;rt = id[rt];}return ret; }2.3、增量最小生成樹
首先找到一顆最小生成樹,之后每加一條邊,在形成的環上刪除權值最大的邊。
2.4、次小生成樹
- 法一:刪除最小生成樹中的一條邊,再重新跑一遍最小生成樹
- 法二:次小生成樹一定可以由最小生成樹加一條邊再刪一條邊得到,因此只要枚舉不在生成樹上的沒一條邊,形成環之后刪除環上的最大邊就可以了。
2.5、最小瓶頸路
- 法一:二分加bfs。
- 法二:最小生成樹上的路就是最小瓶頸路。
2.6、生成樹計數問題
Matrix-tree:
//C[i][j]=無相圖的度數矩陣-無相圖的鄰接矩陣 //Det求n-1階主子式的行列式 LL Det(int n) {LL ret = 1;int f = 1;for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {C[i][j] = (C[i][j] % mod + mod) % mod;}}for (int i = 1; i <= n; i++) {for (int j = i + 1; j <= n; j++) {int A = C[i][i], B = C[j][i];while (B != 0) {LL t = A / B; A = A%B; swap(A, B);for (int k = i; k <= n; k++) {C[i][k] = (C[i][k] - t*C[j][k] % mod + mod) % mod;}for (int k = i; k <= n; k++) {swap(C[i][k], C[j][k]);}f = -f;}}ret = ret*C[i][i] % mod;}if (f == -1) ret = ((-ret) % mod + mod) % mod;return ret; }3、LCA
3.1、在線倍增
//dep:深度,fa:父親,anc:祖先 int dep[maxn]; int anc[maxn][maxm]; void dfs(int u,int f,int d) {dep[u]=d;anc[u][0]=f;for(int i=1; i<maxm; i++) {anc[u][i]=anc[anc[u][i-1]][i-1];}for(int p=head[u]; p!=-1; p=egs[p].ne) {Edge& e=egs[p];if(e.v==f) continue;dfs(e.v,u,d+1);} }int Lca(int u,int v) {if(dep[u]<dep[v]) swap(u,v);for(int i=maxm-1; i>=0; i--) {if(dep[anc[u][i]]>=dep[v]) {u=anc[u][i];}}if(u==v) return u;for(int i=maxm-1; i>=0; i--) {if(anc[u][i]!=anc[v][i]) {u=anc[u][i];v=anc[v][i];}}return anc[u][0]; }void init(){clr(anc[0],0); }轉載于:https://www.cnblogs.com/fenice/p/5702077.html
總結
- 上一篇: 多媒体文件格式之RMVB
- 下一篇: template_1