voidbfs(int start){ queue<int> q; q.push(start); visited[start] = true; while (!q.empty()) { int node = q.front(); q.pop(); cout << node << " "; for (int i = 0; i < graph[node].size(); i++) { int next = graph[node][i]; if (!visited[next]) { q.push(next); visited[next] = true; } } } } intmain(){ int n, m; cin >> n >> m; // 输入图的节点数和边数 graph.resize(n); visited.resize(n, false); for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; // 输入边的两个节点 graph[u].push_back(v); graph[v].push_back(u); // 无向图需要加上这一行 } bfs(0); // 从节点0开始广度优先搜索 return0; }
voiddfs(int node){ cout << node << " "; visited[node] = true; for (int i = 0; i < graph[node].size(); i++) { int next = graph[node][i]; if (!visited[next]) { dfs(next); } } }
intmain(){ int n, m; cin >> n >> m; // 输入图的节点数和边数 graph.resize(n); visited.resize(n, false); for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; // 输入边的两个节点 graph[u].push_back(v); graph[v].push_back(u); // 无向图需要加上这一行 } dfs(0); // 从节点0开始深度优先搜索 return0; }
vector<vector<pair<int, int>>> graph(n+2); voidaddEdge(vector<vector<pair<int, int>>>& graph, int u, int v, int w){ graph[u].push_back({v, w}); } longlong dist[305][305]; voiddijkstra(vector<vector<pair<int, int>>>& graph, int start){
while (!pq.empty()) { int u = pq.top().second; pq.pop();
for (auto edge : graph[u]) { int v = edge.first; int w = edge.second; if (dist[start][u] + w < dist[start][v]) { dist[start][v] = dist[start][u] + w; pq.push({dist[start][v], v}); } } }
}
2. Floyd-Warshall算法求所有结点最短路径
时间复杂度为$O(n^3)$
1 2 3 4 5 6
voidfloyd(){ for(int k = 1; k <= n; k ++) for(int i = 1; i <= n; i ++) for(int j = 1; j <= n; j ++) d[i][j] = min(d[i][j],d[i][k] + d[k][j]); }
状态表示:我们用$d [ k , i , j ]$表示从i走到j,且中间经过的点的编号不超过k的所有路径长度的最小值,什么叫做中间经过点的编号不超过k呢?假设i到j中间经过所有点为$a_1 , a_2 , . . . ,a_m$
,那么这m个点的编号值都$<= k$ ,注意不要与总共经过不超过k个点混淆。
状态计算:$d [ k , i , j ]$的计算可以分为两类:
从i走到j,且中间经过的点的编号不超过k且不包含k的所有节点路径:那么它就等价于从i走到j且经过的点的编号不超过k - 1的所有路径的最小值,即$d [ k − 1 , i , j ]$
从i走到k,且中间经过的点的编号不超过k - 1的所有节点路径的最小值,即$d [ k − 1 , i , k ] $ 从k走到j,且中间经过的点的编号不超过k - 1的所有节点路径的最小值,即$d [ k − 1 , k , j ] $ 并且前后两段是没有关系的,所以这种情况的表示就是$d [k − 1 ,i, k ] + d [ k − 1 , k , j ] $
因此,我们可以得出$d [ k , i , j ] = m i n ( d [ k − 1 , i , j ] , d [k − 1 , i , k ] + d [ k − 1 , k , j ] ) $
structEdge { int x, y, w; booloperator<(const Edge &b) const { return w < b.w; } } e[E_MAX];
int v[V_MAX];
intFind(int x); boolisUnion(int x, int y); voidUnion(int x, int y); //合并 voidmakeSet(int n); //初始化并查集
intmain(){ int n, m; cin >> n >> m; makeSet(n); for (int i = 0; i < m; i++) cin >> e[i].x >> e[i].y >> e[i].w; sort(e, e + m); int cnt = 0; ll sum = 0; for(int i = 0; cnt < n - 1; i++){ if(isUnion(e[i].x, e[i].y)) continue; cnt++; sum += e[i].w; Union(e[i].x, e[i].y); } cout << sum; return0; }
voidmakeSet(int n){ for (int i = 1; i <= n; i++) v[i] = i; }