单源最短路Dij
单源最短路,不包括负权
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 int d[maxn];bool vis[maxn];int mp[maxn][maxn];void Dij (int s) { d[s] = 0 ; for (int i = 0 ;i<n;i++) { int u = -1 ;mn = 1e9 ; for (int j = 0 ;j<n;j++) { if (vis[j]==false && d[j]<mn) { mn = d[j]; u = j; } } if (u==-1 ) return ; vis[u] = true ; for (int v = 0 ;v<n;v++) { if (vis[v]==false && mp[u][v]!=INF && d[u]+mp[u][v]<d[v]) { d[v] = d[u] + mp[u][v]; } } } }
新增边权
用\(cost[u][v]\) 来代表\(u\to v\) 的花费,需要增加一个数组\(c[]\) ,代表从起点\(s\) 到达顶点\(u\) 的最小花费\(c[u]\) ,第一条件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 for (int v = 0 ; v<n ; v++) { if (vis[v]==false && mp[u][v]!=INF) { if (d[v]>d[u]+mp[u][v]) { d[v] = d[u] + mp[u][v]; c[v] = c[u] + cost[u][v]; }else if (d[v]==d[u]+mp[u][v] && cost[u][v] + c[u]<c[v]) { c[v] = cost[u][v] + c[u]; } } }
计算最短路径条数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 for (int v = 0 ; v<n ; v++) { if (vis[v]==false && mp[u][v]!=INF) { if (d[v]>d[u]+mp[u][v]) { d[v] = d[u] + mp[u][v]; num[v] = num[u]; }else if (d[v]==d[u]+mp[u][v]) { num[v] += num[u]; } } }
全源最短路Folyd
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void Floyd () { for (int k = 0 ;k<n;k++) { for (int i = 0 ;i<n;i++) { for (int j = 0 ;j<n;j++) { if (dis[i][k]!=INF && dis[k][j]!=INF && dis[i][k]+dis[k][j]<dis[i][j]) { dis[i][j] = dis[i][k] + dis[k][j]; } } } } }
最小生成树 krustal
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 const int maxn = 1e5 ;struct edge { int u,v; int cost; }e[maxn];bool cmp (edge a,edge b) { return a.cost<b.cost; }int fa[maxn];int find (int x) { if (fa[x]==x) return x; else { fa[x] = find (fa[x]); return fa[x]; } }void Union (int x,int y) { int a = find (x); int b = find (y); if (a!=b) { fa[a] = b; } }int kru (int n,int m) { sort (e,e+m,cmp); int sum = 0 ; for (int i = 0 ;i<n;i++) { fa[i] = i; } int es = 0 ; for (int i = 0 ;i<m;i++) { int a = find (e.u); int b = find (e.v); if (a!=b) { es++; Union (a,b); sum += e.cost; } if (es==n-1 ){ return sum; } } return -1 ; }
BFS广搜
一定一定要注意初始化!!! 如果多次调用的话
邻接矩阵
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 int maxn = 1e5 + 6 ;int mp[maxn][maxn];int vis[maxn];int n;int [] bfs (int a,int b,int dist[maxn]) { for (int i = 1 ;i<=n;i++) { vis[i] = 0 ; dist[i] = 0 ; } queue<int >q; q.push (a); while (!q.empty ()) { int front = q.front (); q.pop (); for (int i = 1 ;i<=n;i++) { if (vis[i]!=0 && mp[front][i] != INF) { q.push (i); vis[i] = 1 ; dist[i] = dist[front] + 1 ; } } } return dist; }
邻接矩阵
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 const int maxn = 1e4 + 6 ;const int INF = 1e8 ;int mp[maxn][maxn];int vis[maxn],dist[maxn];int n,m;void bfs (int a,int b) { for (int i = 1 ;i<=n;i++) { vis[i] = 0 ; dist[i] = -1 ; } queue<int >q; q.push (a); dist[a] = 0 ; vis[a] = 1 ; while (!q.empty ()) { int front = q.front (); q.pop (); for (int i = 1 ;i<=n;i++) { if (vis[i]==0 && mp[front][i] != INF) { cout << front <<" " << i <<" " <<mp[front][i] <<"\n" ; q.push (i); vis[i] = 1 ; dist[i] = dist[front] + 1 ; } } } }
邻接表的处理方法
在n个结点的图里,输入n-1个边,构成一棵树,广搜可构成基环树(最小的环要不小于4)的方法数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include <bits/stdc++.h> using namespace std;const int maxn = 1e5 +6 ; map<int ,vector<int > > mp;int vis[maxn];int d[maxn];int n;int bfs (int x) { for (int i = 0 ;i<=n;i++) { d[i] = 0 ; vis[i] = 0 ; } queue<int >q; q.push (x); d[x] = 0 ; vis[x] = 1 ; int sum = 1 ; while (!q.empty ()) { int top = q.front (); q.pop (); for (int i = 0 ;i<mp[top].size ();i++) { int nw = mp[top][i]; if (vis[nw]==0 ) { vis[nw] = 1 ; d[nw] = d[top]+1 ; q.push (nw); if (d[nw]>=3 ) return sum; sum++; } } } return sum; }int main () { cin >> n; for (int i = 0 ;i<n-1 ;i++) { int u,v; cin >> u >> v; mp[u].push_back (v); mp[v].push_back (u); } int sum = 0 ; for (int i = 1 ;i<=n;i++) { sum += (n-bfs (i)); } cout << sum/2 ; return 0 ; }