【算法笔记自学】第 10 章 提高篇(4)——图算法专题

10.1图的定义和相关术语

#include <cstdio>const int MAXN = 100;
int degree[MAXN] = {0};int main() {int n, m, u, v;scanf("%d%d", &n, &m);for (int j = 0; j < m; j++) {scanf("%d%d", &u, &v);degree[u]++;degree[v]++;}for (int i = 0; i < n; i++) {printf("%d", degree[i]);if (i < n - 1) {printf(" ");}}return 0;
}

#include <cstdio>const int MAXN = 100;
int inDegree[MAXN] = {0};
int outDegree[MAXN] = {0};int main() {int n, m, u, v;scanf("%d%d", &n, &m);for (int j = 0; j < m; j++) {scanf("%d%d", &u, &v);outDegree[u]++;inDegree[v]++;}for (int i = 0; i < n; i++) {printf("%d %d\n", inDegree[i], outDegree[i]);}return 0;
}

10.2图的存储

#include <cstdio>
#include <cstring>const int MAXN = 100;
int G[MAXN][MAXN];int main() {memset(G, 0, sizeof(G));int n, m, u, v;scanf("%d%d", &n, &m);for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u][v] = G[v][u] = 1;}for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {printf("%d", G[i][j]);printf(j < n - 1 ? " " : "\n");}}return 0;
}

#include <cstdio>
#include <cstring>const int MAXN = 100;
int G[MAXN][MAXN];int main() {memset(G, 0, sizeof(G));int n, m, u, v;scanf("%d%d", &n, &m);for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u][v] = 1;}for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {printf("%d", G[i][j]);printf(j < n - 1 ? " " : "\n");}}return 0;
}

#include <cstdio>
#include <vector>
using namespace std;const int MAXN = 100;
vector<int> G[MAXN];int main() {int n, m, u, v;scanf("%d%d", &n, &m);for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);G[v].push_back(u);}for (int i = 0; i < n; i++) {printf("%d(%d)", i, (int)G[i].size());for (int j = 0; j < G[i].size(); j++) {printf(" %d", G[i][j]);}printf("\n");}return 0;
}

#include <cstdio>
#include <vector>
using namespace std;const int MAXN = 100;
vector<int> G[MAXN];int main() {int n, m, u, v;scanf("%d%d", &n, &m);for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);}for (int i = 0; i < n; i++) {printf("%d(%d)", i, (int)G[i].size());for (int j = 0; j < G[i].size(); j++) {printf(" %d", G[i][j]);}printf("\n");}return 0;
}

10.3图的遍历

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;const int MAXN = 100;
vector<int> G[MAXN];
bool vis[MAXN];void DFS(int u) {vis[u] = true;for (int i = 0; i < G[u].size(); i++) {int v = G[u][i];if (!vis[v]) {DFS(v);}}
}int main() {memset(vis, false, sizeof(vis));int n, m, u, v;scanf("%d%d", &n, &m);for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);G[v].push_back(u);}int blockCount = 0;for (int i = 0; i < n; i++) {if (!vis[i]) {DFS(i);blockCount++;}}printf("%d", blockCount);return 0;
}

#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;const int MAXN = 100;
vector<int> G[MAXN];
bool vis[MAXN];void DFS(int u) {vis[u] = true;for (int i = 0; i < G[u].size(); i++) {int v = G[u][i];if (!vis[v]) {DFS(v);}}
}int main() {memset(vis, false, sizeof(vis));int n, m, u, v;scanf("%d%d", &n, &m);for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);G[v].push_back(u);}int blockCount = 0;for (int i = 0; i < n; i++) {if (!vis[i]) {DFS(i);blockCount++;}}printf(blockCount == 1 ? "Yes" : "No");return 0;
}

#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;const int MAXN = 100;
vector<int> G[MAXN];
int vis[MAXN];bool isCyclic(int u) {vis[u] = 0;for (int i = 0; i < G[u].size(); i++) {int v = G[u][i];if (vis[v] == -1 && isCyclic(v)) {return true;} else if (vis[v] == 0) {return true;}}vis[u] = 1;return false;
}int main() {memset(vis, -1, sizeof(vis));int n, m, u, v;scanf("%d%d", &n, &m);for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);}int isCyclicResult = false;for (int i = 0; i < n; i++) {if (vis[i] == -1 && isCyclic(i)) {isCyclicResult = true;}if (isCyclicResult) {break;}}printf(isCyclicResult ? "Yes" : "No");return 0;
}

#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
using namespace std;const int MAXN = 100;
int weight[MAXN];
vector<int> G[MAXN];
bool vis[MAXN];int DFS(int u) {vis[u] = true;int weightSum = weight[u];for (int i = 0; i < G[u].size(); i++) {int v = G[u][i];if (!vis[v]) {weightSum += DFS(v);}}return weightSum;
}int main() {memset(vis, false, sizeof(vis));int n, m, u, v;scanf("%d%d", &n, &m);for (int i = 0; i < n; i++) {scanf("%d", &weight[i]);}for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);G[v].push_back(u);}int maxWeightSum = 0;for (int i = 0; i < n; i++) {if (!vis[i]) {maxWeightSum = max(maxWeightSum, DFS(i));}}printf("%d", maxWeightSum);return 0;
}

#include <cstdio>
#include <vector>
#include <queue>
using namespace std;const int MAXN = 100;
vector<int> G[MAXN];
bool inQueue[MAXN] = {false};
int layers[MAXN];void BFS(int s) {queue<int> q;q.push(s);inQueue[s] = true;int layer = 0;while (!q.empty()) {int cnt = q.size();for (int i = 0; i < cnt; i++) {int front = q.front();q.pop();layers[front] = layer;for (int j = 0; j < G[front].size(); j++) {int v = G[front][j];if (!inQueue[v]) {q.push(v);inQueue[v] = true;}}}layer++;}
}int main() {int n, m, start, u, v;scanf("%d%d%d", &n, &m, &start);for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);G[v].push_back(u);}BFS(start);for (int i = 0; i < n; i++) {printf("%d", layers[i]);if (i < n - 1) {printf(" ");}}return 0;
}

#include <cstdio>
#include <vector>
#include <queue>
using namespace std;const int MAXN = 100;
vector<int> G[MAXN];
bool inQueue[MAXN] = {false};int BFS(int s, int maxLayer) {queue<int> q;q.push(s);inQueue[s] = true;int layer = 0;int vertexCount = 0;while (!q.empty() && layer <= maxLayer) {int cnt = q.size();vertexCount += cnt;for (int i = 0; i < cnt; i++) {int front = q.front();q.pop();for (int j = 0; j < G[front].size(); j++) {int v = G[front][j];if (!inQueue[v]) {q.push(v);inQueue[v] = true;}}}layer++;}return vertexCount;
}int main() {int n, m, start, maxLayer, u, v;scanf("%d%d%d%d", &n, &m, &start, &maxLayer);for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);}int vertexCount = BFS(start, maxLayer);printf("%d", vertexCount);return 0;
}

10.4最短路径

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;const int MAXN = 100;
const int INF = 1e9;struct Edge {int v, dis;Edge(int _v, int _dis) {v = _v, dis = _dis;}
};vector<Edge> G[MAXN];
int d[MAXN];
bool vis[MAXN];void dijkstra(int n, int s) {fill(d, d + MAXN, INF);memset(vis, false, sizeof(vis));d[s] = 0;for (int i = 0; i < n; i++) {int u = -1, minDis = INF;for (int j = 0; j < n; j++) {if (!vis[j] && d[j] < minDis) {u = j;minDis = d[j];}}if (u == -1) {return;}vis[u] = true;for (int j = 0; j < G[u].size(); j++) {int v = G[u][j].v;int dis = G[u][j].dis;if (!vis[v] && d[u] + dis < d[v]) {d[v] = d[u] + dis;}}}
}int main() {int n, m, s, t;scanf("%d%d%d%d", &n, &m, &s, &t);int u, v, w;for (int i = 0; i < m; i++) {scanf("%d%d%d", &u, &v, &w);G[u].push_back(Edge(v, w));G[v].push_back(Edge(u, w));}dijkstra(n, s);if (d[t] == INF) {printf("-1");} else {printf("%d", d[t]);}return 0;
}

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;const int MAXN = 100;
const int INF = 1e9;struct Edge {int v, dis;Edge(int _v, int _dis) {v = _v, dis = _dis;}
};vector<Edge> G[MAXN];
int d[MAXN];
bool vis[MAXN];void dijkstra(int n, int s) {fill(d, d + MAXN, INF);memset(vis, false, sizeof(vis));d[s] = 0;for (int i = 0; i < n; i++) {int u = -1, minDis = INF;for (int j = 0; j < n; j++) {if (!vis[j] && d[j] < minDis) {u = j;minDis = d[j];}}if (u == -1) {return;}vis[u] = true;for (int j = 0; j < G[u].size(); j++) {int v = G[u][j].v;int dis = G[u][j].dis;if (!vis[v] && d[u] + dis < d[v]) {d[v] = d[u] + dis;}}}
}int main() {int n, m, s;scanf("%d%d%d", &n, &m, &s);int u, v, w;for (int i = 0; i < m; i++) {scanf("%d%d%d", &u, &v, &w);G[u].push_back(Edge(v, w));G[v].push_back(Edge(u, w));}dijkstra(n, s);for (int i = 0; i < n; i++) {if (d[i] == INF) {printf("-1");} else {printf("%d", d[i]);}if (i < n - 1) {printf(" ");}}return 0;
}

 

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;const int MAXN = 100;
const int INF = 1e9;struct Edge {int v, dis, cost;Edge(int _v, int _dis, int _cost) {v = _v, dis = _dis, cost = _cost;}
};vector<Edge> G[MAXN];
int d[MAXN], c[MAXN];
bool vis[MAXN];void dijkstra(int n, int s) {fill(d, d + MAXN, INF);fill(c, c + MAXN, INF);memset(vis, false, sizeof(vis));d[s] = 0;c[s] = 0;for (int i = 0; i < n; i++) {int u = -1, minDis = INF;for (int j = 0; j < n; j++) {if (!vis[j] && d[j] < minDis) {u = j;minDis = d[j];}}if (u == -1) {return;}vis[u] = true;for (int j = 0; j < G[u].size(); j++) {int v = G[u][j].v;int dis = G[u][j].dis;int cost = G[u][j].cost;if (!vis[v]) {if (d[u] + dis < d[v]) {d[v] = d[u] + dis;c[v] = c[u] + cost;} else if (d[u] + dis == d[v] && c[u] + cost < c[v]) {c[v] = c[u] + cost;}}}}
}int main() {int n, m, s, t;scanf("%d%d%d%d", &n, &m, &s, &t);int u, v, dis, cost;for (int i = 0; i < m; i++) {scanf("%d%d%d%d", &u, &v, &dis, &cost);G[u].push_back(Edge(v, dis, cost));G[v].push_back(Edge(u, dis, cost));}dijkstra(n, s);printf("%d %d", d[t], c[t]);return 0;
}

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;const int MAXN = 100;
const int INF = 1e9;struct Edge {int v, dis;Edge(int _v, int _dis) {v = _v, dis = _dis;}
};vector<Edge> G[MAXN];
int d[MAXN], pathCount[MAXN];
bool vis[MAXN];void dijkstra(int n, int s) {fill(d, d + MAXN, INF);memset(pathCount, 0, sizeof(pathCount));memset(vis, false, sizeof(vis));d[s] = 0;pathCount[s] = 1;for (int i = 0; i < n; i++) {int u = -1, minDis = INF;for (int j = 0; j < n; j++) {if (!vis[j] && d[j] < minDis) {u = j;minDis = d[j];}}if (u == -1) {return;}vis[u] = true;for (int j = 0; j < G[u].size(); j++) {int v = G[u][j].v;int dis = G[u][j].dis;if (!vis[v]) {if (d[u] + dis < d[v]) {d[v] = d[u] + dis;pathCount[v] = pathCount[u];} else if (d[u] + dis == d[v]) {pathCount[v] += pathCount[u];}}}}
}int main() {int n, m, s, t;scanf("%d%d%d%d", &n, &m, &s, &t);int u, v, w;for (int i = 0; i < m; i++) {scanf("%d%d%d", &u, &v, &w);G[u].push_back(Edge(v, w));G[v].push_back(Edge(u, w));}dijkstra(n, s);printf("%d %d", d[t], pathCount[t]);return 0;
}

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;const int MAXN = 100;
const int INF = 1e9;struct Edge {int v, dis;Edge(int _v, int _dis) {v = _v, dis = _dis;}
};vector<Edge> G[MAXN];
int d[MAXN], pre[MAXN];
bool vis[MAXN];void dijkstra(int n, int s) {fill(d, d + MAXN, INF);memset(pre, -1, sizeof(pre));memset(vis, false, sizeof(vis));d[s] = 0;for (int i = 0; i < n; i++) {int u = -1, minDis = INF;for (int j = 0; j < n; j++) {if (!vis[j] && d[j] < minDis) {u = j;minDis = d[j];}}if (u == -1) {return;}vis[u] = true;for (int j = 0; j < G[u].size(); j++) {int v = G[u][j].v;int dis = G[u][j].dis;if (!vis[v] && d[u] + dis < d[v]) {d[v] = d[u] + dis;pre[v] = u;}}}
}vector<int> path;void DFS(int v, int s) {if (v == s) {path.push_back(v);return;}DFS(pre[v], s);path.push_back(v);
}int main() {int n, m, s, t;scanf("%d%d%d%d", &n, &m, &s, &t);int u, v, w;for (int i = 0; i < m; i++) {scanf("%d%d%d", &u, &v, &w);G[u].push_back(Edge(v, w));G[v].push_back(Edge(u, w));}dijkstra(n, s);DFS(t, s);printf("%d ", d[t]);for (int i = 0; i < path.size(); i++) {printf("%d", path[i]);if (i < (int)path.size() - 1) {printf("->");}}return 0;
}

#include <cstdio>
#include <algorithm>
using namespace std;const int MAXN = 50;
const int INF = 1e9;int d[MAXN][MAXN];void floyd(int n) {for (int k = 0; k < n; k++) {for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (d[i][k] != INF && d[k][j] != INF && d[i][k] + d[k][j] < d[i][j]) {d[i][j] = d[i][k] + d[k][j];}}}}
}int main() {int n, m;scanf("%d%d", &n, &m);fill(d[0], d[0] + MAXN * MAXN, INF);for (int i = 0; i < n; i++) {d[i][i] = 0;}int u, v, w;for (int i = 0; i < m; i++) {scanf("%d%d%d", &u, &v, &w);d[u][v] = d[v][u] = w;}floyd(n);for (int i = 0; i < n; i++) {for (int j = 0; j < n; j++) {if (d[i][j] == INF) {printf("-1");} else {printf("%d", d[i][j]);}if (j < n - 1) {printf(" ");}}printf("\n");}return 0;
}

10.5最小生成树

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;const int MAXN = 500;
const int INF = 1e9;struct Edge {int v, dis;Edge(int _v, int _dis) {v = _v, dis = _dis;}
};vector<Edge> G[MAXN];
int d[MAXN];
bool vis[MAXN];int prim(int n) {fill(d, d + MAXN, INF);memset(vis, false, sizeof(vis));d[0] = 0;int weightSum = 0;for (int i = 0; i < n; i++) {int u = -1, minDis = INF;for (int j = 0; j < n; j++) {if (!vis[j] && d[j] < minDis) {u = j;minDis = d[j];}}if (u == -1) {return -1;}vis[u] = true;weightSum += d[u];for (int j = 0; j < G[u].size(); j++) {int v = G[u][j].v;int dis = G[u][j].dis;if (!vis[v] && dis < d[v]) {d[v] = dis;}}}return weightSum;
}int main() {int n, m;scanf("%d%d", &n, &m);int u, v, w;for (int i = 0; i < m; i++) {scanf("%d%d%d", &u, &v, &w);G[u].push_back(Edge(v, w));G[v].push_back(Edge(u, w));}int weightSum = prim(n);printf("%d", weightSum);return 0;
}

#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;const int MAXN = 10000;struct Edge {int u, v, w;Edge(int _u, int _v, int _w) {u = _u, v = _v, w = _w;}
};vector<Edge> edges;bool cmp(Edge a, Edge b) {return a.w < b.w;
}int father[MAXN];int findFather(int x) {int xCopy = x;while (father[x] != x) {x = father[x];}int root = x;x = xCopy;while (father[x] != x) {int fatherX = father[x];father[x] = root;x = fatherX;}return root;
}int kruskal(int n, int m) {for (int i = 0; i < n; i++) {father[i] = i;}int weightSum = 0, edgeCount = 0;sort(edges.begin(), edges.end(), cmp);for (int i = 0; i < m; i++) {int faU = findFather(edges[i].u);int faV = findFather(edges[i].v);if (faU != faV) {father[faU] = faV;weightSum += edges[i].w;edgeCount++;}if (edgeCount == n - 1) {break;}}if (edgeCount != n - 1) {return -1;} else {return weightSum;}
}int main() {int n, m;scanf("%d%d", &n, &m);int u, v, w;for (int i = 0; i < m; i++) {scanf("%d%d%d", &u, &v, &w);edges.push_back(Edge(u, v, w));}int weightSum = kruskal(n, m);printf("%d", weightSum);return 0;
}

10.6拓扑排序

#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;const int MAXN = 100;vector<int> G[MAXN];
int inDegree[MAXN];
vector<int> topoOrder;void topoSort(int n) {priority_queue<int, vector<int>, greater<int> > q;for (int i = 0; i < n; i++) {if (inDegree[i] == 0) {q.push(i);}}while (!q.empty()) {int u = q.top();q.pop();topoOrder.push_back(u);for (int i = 0; i < G[u].size(); i++) {int v = G[u][i];inDegree[v]--;if (inDegree[v] == 0) {q.push(v);}}G[u].clear();}
}int main() {int n, m;scanf("%d%d", &n, &m);int u, v;for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);inDegree[v]++;}topoSort(n);for (int i = 0; i < topoOrder.size(); i++) {printf("%d", topoOrder[i]);if (i < (int)topoOrder.size() - 1) {printf(" ");}}return 0;
}

#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;const int MAXN = 100;vector<int> G[MAXN];
int inDegree[MAXN];bool topoSort(int n) {int vertexCount = 0;priority_queue<int, vector<int>, greater<int> > q;for (int i = 0; i < n; i++) {if (inDegree[i] == 0) {q.push(i);}}while (!q.empty()) {int u = q.top();q.pop();for (int i = 0; i < G[u].size(); i++) {int v = G[u][i];inDegree[v]--;if (inDegree[v] == 0) {q.push(v);}}G[u].clear();vertexCount++;}return vertexCount == n;
}int main() {int n, m;scanf("%d%d", &n, &m);int u, v;for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);inDegree[v]++;}printf(topoSort(n) ? "Yes" : "No");return 0;
}

#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;const int MAXN = 100;vector<int> G[MAXN];
int inDegree[MAXN];
vector<int> topoOrder;int topoSort(int n) {int vertexCount = 0;priority_queue<int, vector<int>, greater<int> > q;for (int i = 0; i < n; i++) {if (inDegree[i] == 0) {q.push(i);}}while (!q.empty()) {int u = q.top();q.pop();topoOrder.push_back(u);for (int i = 0; i < G[u].size(); i++) {int v = G[u][i];inDegree[v]--;if (inDegree[v] == 0) {q.push(v);}}G[u].clear();vertexCount++;}return vertexCount;
}int main() {int n, m;scanf("%d%d", &n, &m);int u, v;for (int i = 0; i < m; i++) {scanf("%d%d", &u, &v);G[u].push_back(v);inDegree[v]++;}int learnCount = topoSort(n);if (learnCount == n) {printf("Yes\n");for (int i = 0; i < topoOrder.size(); i++) {printf("%d", topoOrder[i]);if (i < (int)topoOrder.size() - 1) {printf(" ");}}} else {printf("No\n%d\n", n - learnCount);}return 0;
}

10.7关键路径

#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;const int MAXN = 100;struct Edge {int v, w;Edge(int _v, int _w) {v = _v, w = _w;}
};vector<Edge> G[MAXN];
int inDegree[MAXN] = {0};
vector<int> topoOrder;
int ve[MAXN], vl[MAXN];
vector<int> activity[MAXN];bool topoSort(int n) {priority_queue<int, vector<int>, greater<int> > q;for (int i = 0; i < n; i++) {if (inDegree[i] == 0) {q.push(i);}}while (!q.empty()) {int u = q.top();q.pop();topoOrder.push_back(u);for (int i = 0; i < G[u].size(); i++) {int v = G[u][i].v;inDegree[v]--;if (inDegree[v] == 0) {q.push(v);}if (ve[u] + G[u][i].w > ve[v]) {ve[v] = ve[u] + G[u][i].w;}}}return (int)topoOrder.size() == n;
}int getCriticalPathLength(int n) {memset(ve, 0, sizeof(ve));if (!topoSort(n)) {return -1;}int maxLength = 0;for(int i = 0; i < n; i++) {if(ve[i] > maxLength) {maxLength = ve[i];}}return maxLength;
}int main() {int n, m;scanf("%d%d", &n, &m);int u, v, w;for (int i = 0; i < m; i++) {scanf("%d%d%d", &u, &v, &w);G[u].push_back(Edge(v, w));inDegree[v]++;}int pathLength = getCriticalPathLength(n);if (pathLength == -1) {printf("No");} else {printf("Yes\n%d", pathLength);}return 0;
}

#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;const int MAXN = 100;struct Edge {int v, w;Edge(int _v, int _w) {v = _v, w = _w;}
};vector<Edge> G[MAXN];
int inDegree[MAXN] = {0};
vector<int> topoOrder;
int ve[MAXN], vl[MAXN];
vector<int> activity[MAXN];bool topoSort(int n) {priority_queue<int, vector<int>, greater<int> > q;for (int i = 0; i < n; i++) {if (inDegree[i] == 0) {q.push(i);}}while (!q.empty()) {int u = q.top();q.pop();topoOrder.push_back(u);for (int i = 0; i < G[u].size(); i++) {int v = G[u][i].v;inDegree[v]--;if (inDegree[v] == 0) {q.push(v);}if (ve[u] + G[u][i].w > ve[v]) {ve[v] = ve[u] + G[u][i].w;}}}return (int)topoOrder.size() == n;
}int getCriticalPath(int n) {memset(ve, 0, sizeof(ve));if (!topoSort(n)) {return -1;}int maxLength = 0;for(int i = 0; i < n; i++) {if(ve[i] > maxLength) {maxLength = ve[i];}}fill(vl, vl + n, maxLength);for (int i = (int)topoOrder.size() - 1; i >= 0; i--) {int u = topoOrder[i];for (int j = 0; j < G[u].size(); j++) {int v = G[u][j].v;int w = G[u][j].w;if (vl[v] - w < vl[u]) {vl[u] = vl[v] - w;}}}for (int u = 0; u < n; u++) {for (int i = 0; i < G[u].size(); i++) {int v = G[u][i].v;int w = G[u][i].w;int e = ve[u], l = vl[v] - w;if (e == l) {activity[u].push_back(v);}}}return maxLength;
}int main() {int n, m;scanf("%d%d", &n, &m);int u, v, w;for (int i = 0; i < m; i++) {scanf("%d%d%d", &u, &v, &w);G[u].push_back(Edge(v, w));inDegree[v]++;}if (getCriticalPath(n) == -1) {printf("No");} else {printf("Yes\n");for (int i = 0; i < n; i++) {sort(activity[i].begin(), activity[i].end());for (int j = 0; j < activity[i].size(); j++) {printf("%d %d\n", i, activity[i][j]);}}}return 0;
}

#include <cstdio>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;const int MAXN = 100;struct Edge {int v, w;Edge(int _v, int _w) {v = _v, w = _w;}
};vector<Edge> G[MAXN];
int inDegree[MAXN] = {0}, inDegreeOrigin[MAXN] = {0};
vector<int> topoOrder;
int ve[MAXN], vl[MAXN];
vector<int> activity[MAXN];bool topoSort(int n) {priority_queue<int, vector<int>, greater<int> > q;for (int i = 0; i < n; i++) {if (inDegree[i] == 0) {q.push(i);}}while (!q.empty()) {int u = q.top();q.pop();topoOrder.push_back(u);for (int i = 0; i < G[u].size(); i++) {int v = G[u][i].v;inDegree[v]--;if (inDegree[v] == 0) {q.push(v);}if (ve[u] + G[u][i].w > ve[v]) {ve[v] = ve[u] + G[u][i].w;}}}return (int)topoOrder.size() == n;
}int getCriticalPath(int n) {memset(ve, 0, sizeof(ve));if (!topoSort(n)) {return -1;}int maxLength = 0;for(int i = 0; i < n; i++) {if(ve[i] > maxLength) {maxLength = ve[i];}}fill(vl, vl + n, maxLength);for (int i = (int)topoOrder.size() - 1; i >= 0; i--) {int u = topoOrder[i];for (int j = 0; j < G[u].size(); j++) {int v = G[u][j].v;int w = G[u][j].w;if (vl[v] - w < vl[u]) {vl[u] = vl[v] - w;}}}for (int u = 0; u < n; u++) {for (int i = 0; i < G[u].size(); i++) {int v = G[u][i].v;int w = G[u][i].w;int e = ve[u], l = vl[v] - w;if (e == l) {activity[u].push_back(v);}}}return maxLength;
}vector<int> criticalPath;
void printCriticalPath(int u) {if(activity[u].size() == 0) {criticalPath.push_back(u);for(int i = 0; i < criticalPath.size(); i++) {printf("%d", criticalPath[i]);if(i < criticalPath.size() - 1) {printf("->");} else {printf("\n");}}criticalPath.pop_back();return;}criticalPath.push_back(u);sort(activity[u].begin(), activity[u].end());for(int i = 0; i < activity[u].size(); i++) {printCriticalPath(activity[u][i]);}criticalPath.pop_back();
}int main() {int n, m;scanf("%d%d", &n, &m);int u, v, w;for (int i = 0; i < m; i++) {scanf("%d%d%d", &u, &v, &w);G[u].push_back(Edge(v, w));inDegree[v]++;inDegreeOrigin[v]++;}if (getCriticalPath(n) == -1) {printf("No");} else {printf("Yes\n");for(int i = 0; i < n; i++) {if(inDegreeOrigin[i] == 0 && activity[i].size() != 0) {printCriticalPath(i);}}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/46293.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自学鸿蒙HarmonyOS的ArkTS语言<九>自定义弹窗组件CustomDialog及二次封装自定义弹窗

一、自定义弹窗 CustomDialog struct CustomDialogBuilder {controller: CustomDialogController new CustomDialogController({ // 注意写法builder: CustomDialogBuilder({})})// controller: CustomDialogController // 这种预览会报错cancel?: () > voidconfirm?: (…

微信小游戏 彩色试管 倒水游戏 逻辑

最近开始研究微信小游戏&#xff0c;有兴趣的 可以关注一下 公众号&#xff0c; 记录一些心路历程和源代码。 定义一个 Cup类&#xff1a; 主要功能 初始化水杯&#xff1a;根据传入的颜色信息初始化水杯中的水层。 倒水&#xff1a;模拟水杯倾斜并倒出水的过程。 加水&…

Prometheus 云原生 - 基于 file_sd、http_sd 实现 Service Discovery

目录 开始 为什么需要服务发现机制 File Service Discovery&#xff08;file_sd&#xff09; 基本概念 配置方式 使用案例 HTTP Service Discovery&#xff08;http_sd&#xff09; 基本概念 配置方式 使用案例 开始 为什么需要服务发现机制 我们知道在 Prometheus …

【链表】算法题(一) ---- 力扣 / 牛客

一、移除链表元素 移除链表中值为val的元素&#xff0c;并返回新的头节点 思路&#xff1a; 题目上这样说&#xff0c;我们就可以创建一个新的链表&#xff0c;将值不为val的节点&#xff0c;尾插到新的链表当中&#xff0c;最后返回新链表的头节点。 typedef struct ListNo…

[安洵杯 2019]easy_web1

知识点&#xff1a; 1.base64加解密 2.md5加解密 3.md5碰撞绕过强类型比较 4.Linux命令绕过 进入页面发现url地址中存在 img参数和一个cmd参数&#xff0c;img参数看上去像是base64编码&#xff0c;可以去尝试一下解码. 进行了两次base64解密得到3535352e706e67看着像16进制那么…

员工聊天记录监控方法大全(五种方法你自己选择)

在现代企业中&#xff0c;为了保障业务安全、防止数据泄露和促进工作效率&#xff0c;很多公司会采用各种方法监控员工的聊天记录。虽然听起来有点“大哥哥在看着你”的感觉&#xff0c;但只要在合法和透明的前提下进行&#xff0c;这其实是为了构建一个更加健康、安全的工作环…

网络流问题-Min-cut

文章目录 1. 网络流问题基础1.1 概述1.2 常规算法1.3 总结 2. Ford-Fulkerson Algorithm2.1 概述2.2 Ford 算法2.3 Ford 算法小结 链接&#xff1a; B站学习视频 1. 网络流问题基础 1.1 概述 最大流问题主要是关于有向图问题。有向图中有m个边&#xff0c; n个节点,其中有一个…

怎么用PPT录制微课?详细步骤解析!

随着信息技术的不断发展&#xff0c;微课作为一种新型的教学形式&#xff0c;因其短小精悍、针对性强等特点&#xff0c;在教育领域得到了广泛的应用。而PPT作为一款常用的演示工具&#xff0c;不仅可以用来制作课件&#xff0c;还可以利用其内置的录屏功能或结合专业的录屏软件…

Dify中的经济索引模式实现过程

当索引模式为经济时&#xff0c;使用离线的向量引擎、关键词索引等方式&#xff0c;降低了准确度但无需花费 Token。 一.提取函数**_extract** 根据不同文档类型进行内容的提取&#xff1a; def _extract(self, index_processor: BaseIndexProcessor, dataset_document: Data…

FastAPI 学习之路(四十三)路径操作的高级配置

在实际开发中&#xff0c;可能我们有些接口不能在接口文档中与其他业务接口一样开放给前端或者其他对接人&#xff0c;那么我们肯定会想着在接口文档中对其进行屏蔽隐藏操作&#xff0c;那么可以实现吗&#xff1f; 接口文档中隐藏接口 当然&#xff0c;还很简单&#xff0c;…

【CSS in Depth 2 精译】2.6 CSS 自定义属性(即 CSS 变量)+ 2.7 本章小结

文章目录 2.6 自定义属性&#xff08;即 CSS 变量&#xff09;2.6.1 动态变更自定义属性 2.7 本章小结 当前内容所在位置 第一章 层叠、优先级与继承第二章 相对单位 2.1 相对单位的威力2.2 em 与 rem2.3 告别像素思维2.4 视口的相对单位2.5 无单位的数值与行高2.6 自定义属性 …

PGCCC|【PostgreSQL】PCA+PCP+PCM等IT类认证申报个税退税指南

小编特将PostgreSQL证书申报个税退税流程&#xff0c;编辑成文&#xff0c;供大家申报参考哦~ 1.申报专项附加扣除 第一步&#xff1a;打开个人所得税APP&#xff0c;选择“专项附加扣除填报”&#xff1a; 第二步&#xff1a;“扣除年度”选择您要申报的年度&#xff0c;并…

Windows 默认以管理员运行打开CMD

winr 默认以管理员打开运行CMD 需求&#xff1a;在运行页面输入cmd 希望是可以直接通过管理员方式打开的。 winr 打开运行 输入secpol.msc 打开本地安全策略&#xff08;注意家庭版是没有这个的&#xff09; 找到本地策略–安全选项–用户帐户控制: 以管理员批准模式运行所有管…

基于Python thinker GUI界面的股票评论数据及投资者情绪分析设计与实现

1.绪论 1.1背景介绍 Python 的 Tkinter 库提供了创建用户界面的工具&#xff0c;可以用来构建股票评论数据及投资者情绪分析的图形用户界面&#xff08;GUI&#xff09;。通过该界面&#xff0c;用户可以输入股票评论数据&#xff0c;然后通过情感分析等技术对评论进行情绪分析…

JavaScript 中 await 永远不会 resolve 的 Promise 会导致内存泄露吗?

前言 在 JavaScript 中&#xff0c;await 关键字用于等待一个 Promise 完成&#xff0c;它只能在异步函数&#xff08;async function&#xff09;内部使用。当 await 一个永远不会 resolve 的 Promise 时&#xff0c;它确实会阻塞异步函数的进一步执行&#xff0c;但不会直接…

C1W1.Assignment: Logistic Regression

理论课&#xff1a;C1W1.Sentiment Analysis with Logistic Regression 文章目录 前期准备导入包导入数据处理推文文本 Part 1: Logistic regressionPart 1.1: Sigmoid实现 sigmoid 函数Logistic regression: regression and a sigmoid Part 1.2 Cost function and GradientUp…

Python 使用proto 发送socket数据

import socket import binascii import struct from SensingMonitoring_pb2 import Command, CommandNamesif __name__ "__main__":client socket.socket(socket.AF_INET, socket.SOCK_STREAM)client.connect(("192.168.1.100", 22295))# 发送数据comman…

软件模块的初始化

什么是初始化&#xff1f; 软件的初始化&#xff08;Initialization&#xff09;是指软件启动或重新配置时执行的一系列步骤和过程&#xff0c;旨在准备软件运行环境、加载必要的配置信息、检查系统依赖项、分配资源&#xff08;如内存、文件句柄等&#xff09;&#xff0c;以及…

5、Hacker_Kid-v1.0.1

中等难度 目标root权限 先进行一波IP地址发现 netdiscover -i eth0 -r 192.168.1.1/24 发现存在的靶机ip 进行一波端口的探测 发现是一个apache的服务和一个tornado的网站 这里有个细节部分&#xff0c;53端口常见的情况都是走的udp协议做的域名解析&#xff0c;这里查询出来…