文章目录
简单的图
1.可能到达所有点的衔接
class Solution {
public:
vector<int> findSmallestSetOfVertices(int n, vector<vector<int>>& edges) {
vector<int> temp(n + 1, 0);
for(int i = 0; i < edges.size(); ++ i ) { ++ temp [边[ i ] [ 1 ] ] ; } 向量< int > res ; for (int i = 0 ; i < n ; ++ i ){ if ( temp [ i ] == 0 ) res 。emplace_back (我); }返回
资源; } } ; ```
## 2.所有可能的路径```的cpp类解{公共: 矢量<矢量< INT >> allPathsSourceTarget (矢量<矢量< INT >> &图表){ INT ñ =曲线图。大小(); 矢量<矢量< INT > >水库; 向量< int >路径{ 0
};
bfs(0, n - 1, path, res, graph);
return res;
}
void bfs(int cur, int end, vector<int> &path, vector<vector<int> > &res, vector<vector<int> > &graph) {
if (cur == end) {
res.emplace_back(path);
return ;
}
for (auto i : graph[cur]) {
path.emplace_back(i);
bfs(i, end, path, res, graph);
path.pop_back();
}
return ;
}
};
3.克隆图
dfs
class Solution {
public:
unordered_map<Node *, Node *> visited;
Node* cloneGraph(Node* node) {
if(node == nullptr) return node;
if (visited.find(node) != visited.end()) {
return visited[node];
}
Node *cloneNode = new Node(node->val);
visited[node] = cloneNode;
for (auto &neigh: node->neighbors) {
cloneNode->neighbors.emplace_back(cloneGraph(neigh));
}
return cloneNode;
}
};
bfs
class Solution {
public:
Node* cloneGraph(Node* node) {
if(node == nullptr) return node;
unordered_map<Node *, Node *> visited;
visited[node] = new Node(node->val);
queue<Node *> que;
que.emplace(node);
while(!que.empty()) {
Node *cur = que.front();
que.pop();
for (auto &neigh: cur->neighbors) {
if (visited.find(neigh) == visited.end()) {
visited[neigh] = new Node(neigh->val);
que.emplace(neigh);
}
visited[cur]->neighbors.emplace_back(visited[neigh]);
}
}
return visited[node];
}
};
4.冗余连接
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
int n = edges.size();
vector<int> fa(n + 5, 0);
init(fa, n);
for (auto e : edges) {
int a = e[0], b = e[1];
if (get(fa, a) != get(fa, b)) {
merge(fa, a, b);
} else {
return e;
}
}
return vector<int> {};
}
void init(vector<int> &fa, int n) {
for (int i = 1; i <= n; i++) {
fa[i] = i;
}
}
int get(vector<int> &fa, int x) {
return fa[x] = (x - fa[x]) ? get(fa, fa[x]) : x;
}
void merge(vector<int> &fa, int a, int b) {
fa[get(fa, a)] = get(fa, b);
}
};
6.钥匙和房间
bfs
class Solution {
public:
bool canVisitAllRooms(vector<vector<int>>& rooms) {
int n = rooms.size();
vector<int> visited(n + 5, 0);
visited[0] = 1;
queue<int> que;
que.emplace(0);
int sum = 1;
while(!que.empty()) {
int cur = que.front();
que.pop();
for (auto key : rooms[cur]) {
if (visited[key] == 0) {
sum += 1;
visited[key] = 1;
que.emplace(key);
}
}
}
return sum == n;
}
};
dfs
class Solution {
public:
bool canVisitAllRooms(vector<vector<int>>& rooms) {
int n = rooms.size();
vector<int> visited(n, 0);
int visit_num = 0;
dfs(rooms, 0, visited, visit_num);
return visit_num == n;
}
void dfs(vector<vector<int> >& rooms, int cur, vector<int> &visited, int &visit_num) {
visited[cur] = 1;
visit_num += 1;
for (auto key : rooms[cur]) {
if (visited[key] == 0) {
dfs(rooms, key, visited, visit_num);
}
}
}
};
7.统计参与通信的服务器
class Solution {
public:
int countServers(vector<vector<int>>& grid) {
int n = grid.size(), m = grid[0].size();
vector<int> every_line_num(n + 1, 0);
vector<int> every_column_num(m + 1, 0);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (grid[i][j] == 1) {
++every_line_num[i];
++every_column_num[j];
}
}
}
int sum = 0;
for(int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (grid[i][j] == 1 && (every_line_num[i] > 1 || every_column_num[j] > 1)) {
++sum;
}
}
}
return sum;
}
};
最短路径
五大算法的时间复杂度
1.floyd
公式
已知起点和终点.
节点数n个, 中转点i, 起点j, 终点k
dir[x][y]是指从x到y的最短路径
求最短路
缺点慢还耗内存
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
dir[j][k] = max(dir[j][k], dir[j][i] + dir[i][k]);
}
}
}
include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
#include<climits>
using namespace std;
const int MAX_N = 100;
void floyd(int n, vector<vector<int> >& dir) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < n; k++) {
dir[j][k] = max(dir[j][k], dir[j][i] + dir[i][k]);
}
}
}
return ;
}
int main() {
int node_num, dir_num, star_node;
cin >> node_num >> dir_num >> star_node;
vector<vector<int> > dir(MAX_N + 5, vector<int>(MAX_N + 5, INT_MAX));
for (int i = 0; i < dir_num; i++) {//自己到自己
dir[i][i] = 0;
}
for (int i = 0; i < dir_num; i++) {
int s, e, l;
cin >> s >> e >> l;
dir[s][e] = min(dir[s][e], l);
}
for (int i = 0; i <= node_num; i++) {
if (i != 1) {
cout << " ";
}
if (dir[star_node][i] == 0x3F3F3F3F) {//路不通
cout << -1;
} else {
cout << dir[star_node][i];
}
}
return 0;
}
链式前向星
head[x]: 以x为起点的最后一条边的编号
struct edg{
int e, dist, next;//e:终点, dist权值, next: 同一个起点的上一条边的编号
};
我们可以通过last_edg = head[x]来查找访问节点x的最后一条边,在通过edg[last_edg] 来查找与last_edg访问同一节点的边,直到出现负边,表示访问该节点的边已经遍历完.
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
struct edge{
int e, dist, next;
};
class Graph{
public:
Graph(int nodeNum, int edgNum): nodeNum(nodeNum), edgNum(edgNum){
head = vector<int>(nodeNum, -1);
edg = vector<edge>(edgNum);
}
void cfs(int edg_number, int sta, int end, int len) {
edg[edg_number].e = end;
edg[edg_number].dist = len;
edg[edg_number].next = head[sta];
head[sta] = edg_number;
}
void printGraphList() {
for (int i = 1; i <= nodeNum; i++) {
cout << i << " :";
for (int j = head[i]; j != -1; j = edg[j].next) {
int e = edg[j].e, d = edg[j].dist;
cout << "(" << e << " " << d << ") ";
}
cout << endl;
}
}
~Graph() {
head.clear();
edg.clear();
}
private:
int nodeNum, edgNum;
vector<int> head;
vector<edge> edg;
};
int main() {
int n, m, s;
cin >> n >> m >> s;
Graph g(n, m);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
g.cfs(i, a, b, c);
}
g.printGraphList();
return 0;
}
2.dijkstra
缺点是不能有负边, 且单元, 起点固定, 只有一个起点
已知一固定起点,终点未知.
#include <iostream>
#include <queue>
#include <cstring>
using namespace std;
struct node {
int now, dist;
bool operator< (const node &b) const {
return this->dist > b.dist;
}
};
int n, m, s, arr[1005][1005], ans[1005];
int main() {
memset(arr, 0x3F, sizeof(arr));
memset(ans, 0x3F, sizeof(ans));
cin >> n >> m >> s;
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
arr[a][b] = min(arr[a][b], c);
}
priority_queue<node> que;
que.push((node){s, 0});
while (!que.empty()) {
node temp = que.top();
que.pop();
if (ans[temp.now] != 0x3F3F3F3F) {
continue;
}
ans[temp.now] = temp.dist;
for (int i = 1; i <= n; i++) {
if (arr[temp.now][i] != 0x3F3F3F3F) {
que.push((node){i, temp.dist + arr[temp.now][i]});
}
}
}
for (int i = 1; i <= n; i++) {
if (i != 1) {
cout << " ";
}
if (ans[i] == 0x3F3F3F3F) {
cout << -1;
} else {
cout << ans[i];
}
}
cout << endl;
return 0;
}
3.优化的dijkstra(链式前向星+dijkstra)
#include<iostream>
#include<queue>
#include<vector>
#include <climits>
using namespace std;
struct edge{
int e, dist, next;
};
class Graph{
public:
Graph() = default;
Graph(int nodenum, int edgNum): __nodeNum(nodenum), edgNum(edgNum){
head = vector<int>(nodenum, -1);
edg = vector<edge>(edgNum);
}
int nodeNum() {
return __nodeNum;
}
void cfs(int edg_number, int sta, int end, int len) {
edg[edg_number].e = end;
edg[edg_number].dist = len;
edg[edg_number].next = head[sta];
head[sta] = edg_number;
return ;
}
int edgend(int x) {
return edg[x].e;
}
int edgdist(int x) {
return edg[x].dist;
}
int edgnext(int x) {
return edg[x].next;
}
int lastedg(int x) {
return head[x];
}
void printGraphList() {
for (int i = 1; i <= __nodeNum; i++) {
cout << i << " :";
for (int j = head[i]; j != -1; j = edg[j].next) {
int e = edg[j].e, d = edg[j].dist;
cout << "(" << e << " " << d << ") ";
}
cout << endl;
}
return ;
}
~Graph() {
head.clear();
edg.clear();
}
private:
int __nodeNum, edgNum;
vector<int> head;
vector<edge> edg;
};
struct node{
int now, dist;
bool operator< (const node &b) const{
return this->dist > b.dist;
}
};
class MinPath{
public:
MinPath(Graph g, int sta):g(g), sta(sta){
minpaths = vector<int>(g.nodeNum() + 1, INT_MAX);
}
void dijkstra() {
que.push((node){sta, 0});
while(!que.empty()) {
node temp = que.top();
que.pop();
if (minpaths[temp.now] > temp.dist) minpaths[temp.now] = temp.dist;
else continue;
for (int i = g.lastedg(temp.now); i != -1; i = g.edgnext(i)) {
int e = g.edgend(i), d = g.edgdist(i);
if (minpaths[e] > minpaths[temp.now] + d) {
que.push((node){e, minpaths[temp.now] + d});
}
}
}
return ;
}
void printMinPath() {
for (int i = 1; i <= g.nodeNum(); i++) {
if (i != 1) {
cout << " ";
}
if (minpaths[i] == 0x3F3F3F3F) {
cout << -1;
} else {
cout << minpaths[i];
}
}
cout << endl;
}
int minpath(int t) {
return minpaths[t];
}
private:
int sta;
priority_queue<node> que;
Graph g;
vector<int> minpaths;
};
int main() {
int n, m, s, t;
cin >> n >> m >> s;
Graph g(n, m);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
g.cfs(i, a, b, c);
}
MinPath p(g, s);
p.dijkstra();
p.printMinPath();
/*while(cin >> t) {
cout << p.minpath(t) << endl;
}
*/
return 0;
}
4.bellman-ford
#include<iostream>
#include<queue>
#include<vector>
#include <climits>
using namespace std;
struct edge{
int e, dist, next;
};
class Graph{
public:
Graph() = default;
Graph(int nodenum, int edgNum): __nodeNum(nodenum), edgNum(edgNum){
head = vector<int>(nodenum, -1);
edg = vector<edge>(edgNum);
}
int nodeNum() {
return __nodeNum;
}
void cfs(int edg_number, int sta, int end, int len) {
edg[edg_number].e = end;
edg[edg_number].dist = len;
edg[edg_number].next = head[sta];
head[sta] = edg_number;
return ;
}
int edgend(int x) {
return edg[x].e;
}
int edgdist(int x) {
return edg[x].dist;
}
int edgnext(int x) {
return edg[x].next;
}
int lastedg(int x) {
return head[x];
}
void printGraphList() {
for (int i = 1; i <= __nodeNum; i++) {
cout << i << " :";
for (int j = head[i]; j != -1; j = edg[j].next) {
int e = edg[j].e, d = edg[j].dist;
cout << "(" << e << " " << d << ") ";
}
cout << endl;
}
return ;
}
~Graph() {
head.clear();
edg.clear();
}
private:
int __nodeNum, edgNum;
vector<int> head;
vector<edge> edg;
};
class MinPath{
public:
MinPath(Graph g, int sta):g(g), sta(sta){
minpaths = vector<int>(g.nodeNum() + 1, INT_MAX);
mark = vector<int>(g.nodeNum() + 1, 0);
}
void bellman_ford() {
que.push(sta);
minpaths[sta] = 0;
while(!que.empty()) {
int temp = que.front();
que.pop();
mark[temp] = 0;
for (int i = g.lastedg(temp); i != -1; i = g.edgnext(i)) {
int e = g.edgend(i), d = g.edgdist(i);
if (minpaths[e] > minpaths[temp] + d) {
minpaths[e] = minpaths[temp] + d;
if (mark[e] == 0) {
que.push(e);
mark[e] = 1;
}
}
}
}
return ;
}
void printMinPath() {
for (int i = 1; i <= g.nodeNum(); i++) {
if (i != 1) cout << " ";
if (minpaths[i] == 0x3F3F3F3F) cout << -1;
else cout << minpaths[i];
}
cout << endl;
return ;
}
int minpath(int t) {
return minpaths[t];
}
private:
int sta;
queue<int> que;
Graph g;
vector<int> minpaths;
vector<int> mark;
};
int main() {
int n, m, s, t;
cin >> n >> m >> s;
Graph g(n, m);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
g.cfs(i, a, b, c);
}
MinPath p(g, s);
p.bellman_ford();
p.printMinPath();
/*while(cin >> t) {
cout << p.minpath(t) << endl;
}
*/
return 0;
}
路径之和
路径之和最小-最小生成树
kruskal
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
struct edge {
int s, e, v;
};
bool cmp(const edge &a, const edge &b) {
return a.v < b.v;
}
class Union {
public:
Union() = default;
Union(int n, int m) : n(n), m(m){
my_union = vector<int>(n);
}
void init() {
for (int i = 1; i <= this->n; i++) {
my_union[i] = i;
}
return ;
}
int get(int x) {
return my_union[x] = (x - my_union[x] ? get(my_union[x]) : x);
}
void merge(int a, int b) {
my_union[a] = b;
}
private:
int n, m;
vector<int> my_union;
};
int main() {
int n, m;
int already = 1, ans = 0;
cin >> n >> m;
vector<edge> edg(m);
for (int i = 0; i < m; i++) {
cin >> edg[i].s >> edg[i].e >> edg[i].v;
}
sort(edg.begin(), edg.end(), cmp);
Union u(n, m);
u.init();
for (int i = 0; i <= m; i++) {
int sr = u.get(edg[i].s), er = u.get(edg[i].e);
if (sr != er) {
already++;
ans += edg[i].v;
u.merge(sr, er);
if (already == n) break;
}
}
if (already == n) {
cout << ans << endl;
} else {
cout << "orz" << endl;
}
return 0;
}
prim
#include<iostream>
#include<queue>
#include<vector>
#include <climits>
using namespace std;
struct edge{
int e, dist, next;
};
class Graph{
public:
Graph() = default;
Graph(int nodenum, int edgNum): __nodeNum(nodenum), edgNum(edgNum){
head = vector<int>(nodenum, -1);
edg = vector<edge>(edgNum);
}
int nodeNum() {
return __nodeNum;
}
void cfs(int edg_number, int sta, int end, int len) {
edg[edg_number].e = end;
edg[edg_number].dist = len;
edg[edg_number].next = head[sta];
head[sta] = edg_number;
return ;
}
int edgend(int x) {
return edg[x].e;
}
int edgdist(int x) {
return edg[x].dist;
}
int edgnext(int x) {
return edg[x].next;
}
int lastedg(int x) {
return head[x];
}
~Graph() {
head.clear();
edg.clear();
}
private:
int __nodeNum, edgNum;
vector<int> head;
vector<edge> edg;
};
struct node{
int now, dist;//dist:到达权值为多少的边到达这个点,越小越好
bool operator< (const node &b) const{
return this->dist > b.dist;
}
};
class MinTree{
public:
MinTree(Graph g, int sta, int ans = 0, int already = 0):g(g), sta(sta), ans(ans), already(already){
n = g.nodeNum();
mark = vector<int>(n + 1, 0);
dis = vector<int>(n + 1, INT_MAX);
}
void mintree() {
que.push((node){sta, 0});
while(!que.empty()) {
node temp = que.top();
que.pop();
if (mark[temp.now] == 1) continue;
mark[temp.now] = 1;
ans += temp.dist;
++already;
if (already == n) break;
for (int i = g.lastedg(temp.now); i != -1; i = g.edgnext(i)) {
int e = g.edgend(i), d = g.edgdist(i);
if (mark[e] == 0 && dis[e] > d) {
dis[e] = d;
que.push((node){e, d});
}
}
}
return ;
}
void print() {
if (already == n) {
cout << ans << endl;
} else {
cout << "arz" << endl;
}
return ;
}
private:
int sta, ans, already, n;
priority_queue<node> que;
Graph g;
vector<int> mark, dis;
};
int main() {
int n, m, s, t;
cin >> n >> m >> s;
Graph g(n, m);
for (int i = 0; i < m; i++) {
int a, b, c;
cin >> a >> b >> c;
g.cfs(i, a, b, c);
}
MinTree p(g, s);
p.mintree();
p.print();
return 0;
}