日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

图论二

發布時間:2025/3/21 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 图论二 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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

總結

以上是生活随笔為你收集整理的图论二的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。