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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

PAT甲级题目翻译+答案 AcWing(图论)

發(fā)布時間:2025/3/19 编程问答 11 豆豆
生活随笔 收集整理的這篇文章主要介紹了 PAT甲级题目翻译+答案 AcWing(图论) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1003 Emergency (25 分)

  • 題意 :求無向圖中最短路的數(shù)量,以及在最短路情況下,點權(quán)之和最大是多少
  • 思路 :dijkstra的擴展一般在第三步“用t更新其它點“;spfa不能用來求最短路的數(shù)量(因為每個點可能被更新多次);假設(shè)有三個點可以走到終點x,那么從起點s走到x的路徑分為三類,s->1->x…,如果d1<d2<d3,最短距離的數(shù)量就是走到第一個點的數(shù)量,如果d1=d2<d3,前兩個相加,同理,求最短路情況下點權(quán)和最大,就是三者取max(如果三者相同);cnt數(shù)組記錄從起點走到i的最短路徑數(shù)量;sum數(shù)組記錄從起點到i的最大點權(quán)
  • 語法 :如果點數(shù)<=1000,鄰接矩陣就沒有問題,>=1e4就一定要鄰接表存;
#include <iostream> #include <cstring>using namespace std;const int N = 510;int n, m, S, T; int w[N], g[N][N]; int cnt[N], sum[N]; int dist[N]; bool st[N];void dijkstra() {memset(dist, 0x3f, sizeof dist); // 初始化dist[S] = 0, cnt[S] = 1, sum[S] = w[S];for (int i = 0; i < n - 1; i ++ ){int t = -1;for (int j = 0; j < n; j ++ )if (!st[j] && (t == -1 || dist[t] > dist[j]))t = j;st[t] = true; // 標記for (int j = 0; j < n; j ++ )if (dist[j] > dist[t] + g[t][j]){dist[j] = dist[t] + g[t][j];cnt[j] = cnt[t];sum[j] = sum[t] + w[j];}else if (dist[j] == dist[t] + g[t][j]){cnt[j] += cnt[t];sum[j] = max(sum[j], sum[t] + w[j]);}} }int main() {cin >> n >> m >> S >> T;for (int i = 0; i < n; i ++ ) cin >> w[i];memset(g, 0x3f, sizeof g); // 初始化while (m -- ){int a, b, c;cin >> a >> b >> c;g[a][b] = g[b][a] = min(g[a][b], c); // 無向圖}dijkstra();cout << cnt[T] << ' ' << sum[T];return 0; }
  • 思路 :dijkstra中在循環(huán)for或者while的外面初始化時,起點的st不要設(shè)成true!堆優(yōu)化版在一個點被更新松弛后將它放入優(yōu)先隊列內(nèi)
  • 語法 :堆優(yōu)化版寫成鏈式前向星,M開成N*N
// 堆優(yōu)化版 #include <iostream> #include <cstring> #include <queue>using namespace std;const int N = 510, M = N * N; // 注意M大小typedef pair<int, int> pii;int h[N], w[M], e[M], ne[M], idx; int wt[N]; int dist[N]; bool st[N]; int cnt[N], sum[N]; int n, m, S, T;void add(int a, int b, int c) {e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ; }void dijkstra() {memset(dist, 0x3f, sizeof dist);dist[S] = 0;cnt[S] = 1, sum[S] = wt[S];priority_queue<pii, vector<pii>, greater<pii>> heap;heap.push({0, S});// st[S] = true; 注意!!!while (heap.size()){auto t = heap.top();heap.pop();int ver = t.second, distance = t.first;if (st[ver]) continue;st[ver] = true;for (int i = h[ver]; i != -1; i = ne[i]){int j = e[i];if (dist[j] > dist[ver] + w[i]){dist[j] = dist[ver] + w[i];cnt[j] = cnt[ver];sum[j] = sum[ver] + wt[j];heap.push({dist[j], j}); // 被更新松弛了的點要放入優(yōu)先隊列內(nèi)}else if (dist[j] == dist[ver] + w[i]){cnt[j] += cnt[ver];sum[j] = max(sum[j], sum[ver] + wt[j]);}}} }int main() {memset(h, -1, sizeof h);cin >> n >> m >> S >> T;for (int i = 0; i < n; i ++ ) cin >> wt[i];while (m -- ){int a, b, c;cin >> a >> b >> c;add(a, b, c);add(b, a, c);}dijkstra();cout << cnt[T] << ' ' << sum[T];return 0; }

1018 Public Bike Management (30 分)

題意 :

  • 給一個終點,要從起點出發(fā),要找到一條路徑,第一優(yōu)先級的要求是 距離最短;如果有很多條距離相同的路徑,第二優(yōu)先級,最初帶去的自行車數(shù)量越少越好;第三優(yōu)先級,最終帶回的自行車數(shù)量越少越好

思路 :

  • 多關(guān)鍵字的dijk,但前面的問題是可以在dijk過程中去滿足,這題比較特殊,后面兩個要求是不能再dijk過程中去滿足的;比如從兩個點中選一個去第三個點,第一個點出發(fā)要帶5輛車,第二個點出發(fā)要帶6輛車,但我們無法分析到底哪個點更好,比如到第三個點恰好缺5輛,第一個點就更好,但也有可能缺6輛,第二個點就更好。像以前的關(guān)鍵字都是累加的,第一關(guān)鍵字距離第二關(guān)鍵字時間,時間肯定越短越好,但這題無法判斷
  • 所以這題就比較復(fù)雜,先做一遍dijk,求每個點終點的最短距離,然后再去把所有從起點到終點的最短距離搜索一遍,從所有的最短路徑中找后兩個條件最好的
  • 這題本應(yīng)是指數(shù)級復(fù)雜度,但對于一個隨機圖而言,最短路徑不會太多
  • 求dijk是為了剪枝,保證走的時候是最短路徑;比如我們當(dāng)前在u點,要判斷u點走到v點有沒有可能使是最短路徑呢?可以用dist數(shù)組判斷,如果dist[u] = dist[u -> v] + dist[v],那么說明我們搜的時候可以從u走到v,這其實就是一個剪枝
  • 用一個變量s表示當(dāng)前需要帶去多少自行車,可以是負數(shù),在過程中,負數(shù)的最小值就是我們需要帶去的自行車;帶回的自行車是多少呢?就是看最終s的值是多少,再加上帶去的數(shù)量
  • 爆搜時用一個vector容器 的 path來存路徑,ans來存答案路徑
  • 當(dāng)爆搜到終點時,在計算需要帶的數(shù)量sd時,此時的mins有可能為正數(shù),也就是一輛都不用帶,所以要和0取最小的,最終需要帶走的數(shù)量bg就是s加上sd
  • 注意這個mins不是全局變量!!是當(dāng)前這條路徑上的最小值
  • dfs時,假設(shè)放了,之后還要回溯pop_back

語法 :

  • s -= (C + 1) / 2 - c[u];是上取整
  • 帶權(quán)無向圖,首先初始化g數(shù)組為無窮;帶權(quán),未說明是否有重邊,因此取min
  • 初始時,dfs前,不要忘了往里面加上起點0
#include <iostream> #include <vector> #include <cstring> using namespace std;#define pb push_backconst int N = 510, INF = 0x3f3f3f3f;int C, n, S, m; int c[N]; int g[N][N]; int dist[N]; bool st[N];vector<int> path, ans;int send = INF, bring = INF;void dijkstra() {memset(dist, 0x3f, sizeof dist);dist[S] = 0;for (int i = 0; i < n; i ++ ){int t = -1;for (int j = 0; j <= n; j ++ )if (!st[j] && (t == -1 || dist[t] > dist[j]))t = j;st[t] = true;for (int j = 0; j <= n; j ++ )dist[j] = min(dist[j], dist[t] + g[t][j]);} }void dfs(int u, int s, int mins) {if (u){s -= (C + 1) / 2 - c[u];mins = min(mins, s);}if (u == S){int sd = abs(min(0, mins));int bg = sd + s;if (sd < send || (sd == send && bring > bg))ans = path, send = sd, bring = bg;return ;}for (int i = 1; i <= n; i ++ )if (dist[u] == dist[i] + g[u][i]){path.pb(i);dfs(i, s, mins);path.pop_back();} }int main() {scanf("%d%d%d%d", &C, &n, &S, &m);for (int i = 1; i <= n && scanf("%d", &c[i]); i ++ );memset(g, 0x3f, sizeof g);for (int i = 0, x, y, z; i < m && scanf("%d%d%d", &x, &y, &z); i ++ )g[x][y] = g[y][x] = min(g[x][y], z);dijkstra();path.pb(0);dfs(0, 0, 0);printf("%d 0", send);for (int i = 1; i < ans.size(); i ++ ) printf("->%d", ans[i]);printf(" %d", bring); }

1122 Hamiltonian Cycle (25 分)

題意 :

  • Hamiltonian Cycle哈密頓回路
  • 哈密頓回路問題是找到一個包含圖中每個頂點的簡單回路。
  • 在本題中,你需要做的是判斷給定路徑是否為哈密頓回路。
  • 無向圖

思路 :

  • 恰好每個點走一次,且第一個點和最后一個點是同一個點
  • 如果滿足了以上兩個要求,就按它給的路徑走一遍,如果從當(dāng)前這個點都能走到下一個點,且所有點都走了一次,就是哈密頓路徑
  • 這題有一個很坑的地方,題目只說了圖中點的數(shù)量是200,但沒說輸入的路徑的點數(shù)也是200,所以如果路徑數(shù)組開太小,會有一個點過不了
#include <iostream> using namespace std;const int N = 210;int n, m; int nodes[N * 2], cnt; bool g[N][N]; bool st[N];bool check() {if (cnt != n + 1 || nodes[0] != nodes[cnt - 1]) return false;for (int i = 1; i <= n; i ++ ) st[i] = 0;for (int i = 0; i < cnt - 1; i ++ ){st[nodes[i]] = true;if (!g[nodes[i]][nodes[i + 1]])return false;}for (int i = 1; i <= n; i ++ )if (!st[i])return false;return true; }int main() {scanf("%d%d", &n, &m);int a, b;while (m -- ){scanf("%d%d", &a, &b);g[a][b] = g[b][a] = true;}int k; scanf("%d", &k);while (k -- ){scanf("%d", &cnt);for (int i = 0; i < cnt; i ++ ) scanf("%d", &nodes[i]);if (check()) puts("YES");else puts("NO");} }

1126 Eulerian Path (25 分)

題意 :

  • Eulerian Path歐拉路徑
  • circuit環(huán)路;degree度數(shù)
  • 歐拉路徑是圖中的一條路徑,該路徑滿足恰好訪問每個邊一次。
  • 歐拉回路是一條在同一頂點處開始和結(jié)束的歐拉路徑。
  • 如果一個連通圖的所有頂點的度數(shù)都為偶數(shù),那么這個連通圖具有歐拉回路,且這個圖被稱為歐拉圖
  • 如果一個連通圖中有兩個頂點的度數(shù)為奇數(shù),其他頂點的度數(shù)為偶數(shù),那么所有歐拉路徑都從其中一個度數(shù)為奇數(shù)的頂點開始,并在另一個度數(shù)為奇數(shù)的頂點結(jié)束。
  • 具有歐拉路徑但不具有歐拉回路的圖被稱為半歐拉圖
  • 現(xiàn)在,給定一個無向圖,請你判斷它是歐拉圖、半歐拉圖還是非歐拉圖。

思路 :

  • 每個點的度數(shù)是什么呢?就是這個點連的邊數(shù)
  • 首先不管是歐拉圖還是半歐拉圖都必須是連通的;所以第一步是判斷連通性,從某個點出發(fā),看能否把所有點搜到,dfs或者bfs;這個判斷連通性是 圖的遍歷,時間復(fù)雜度為 點數(shù)加邊數(shù)
  • 然后判斷度數(shù),直接按照定義即可
  • 判斷連通性的寫法 :從1號點出發(fā),看能搜到幾個點,遍歷的時候為了避免重復(fù)搜索,要有一個判重數(shù)組
#include <iostream> using namespace std;const int N = 510;int n, m; bool g[N][N]; int d[N]; bool st[N]; // dfs用int dfs(int u) {st[u] = true;int cnt = 1;for (int i = 1; i <= n; i ++ ){if (!st[i] && g[u][i])cnt += dfs(i);}return cnt; }int main() {scanf("%d%d", &n, &m);int a, b;while (m -- ){scanf("%d%d", &a, &b);g[a][b] = g[b][a] = true;d[a] ++ , d[b] ++ ;}int cnt = dfs(1);printf("%d", d[1]);for (int i = 2; i <= n; i ++ ) printf(" %d", d[i]);puts("");if (cnt == n){int s = 0;for (int i = 1; i <= n; i ++ )if (d[i] % 2)s ++ ;if (!s) puts("Eulerian");else if (s == 2) puts("Semi-Eulerian");else puts("Non-Eulerian");}elseputs("Non-Eulerian"); }

1134 Vertex Cover (25 分)

題意 :

  • 如果圖中的一個頂點集合能夠滿足圖中的每一條邊都至少有一個端點在該集合內(nèi),那么這個頂點集合就是圖的頂點覆蓋。
  • 現(xiàn)在給定一張圖,以及若干個頂點集合,請你判斷這些頂點集合是否是圖的頂點覆蓋。

思路 :

  • 直接模擬即可
#include <iostream> #include <cstring>using namespace std;const int N = 10010;int n, m; struct Edge {int a, b; }e[N]; bool st[N];int main() {cin >> n >> m;for (int i = 0; i < m; i ++ ) cin >> e[i].a >> e[i].b;int k;cin >> k;while (k -- ){int cnt;cin >> cnt;memset(st, 0, sizeof st);while (cnt -- ){int x;cin >> x;st[x] = true;}int i;for (i = 0; i < m; i ++ )if (!st[e[i].a] && !st[e[i].b])break;if (i == m) puts("Yes");else puts("No");}return 0; }

1142 Maximal Clique (25 分)

題意 :

  • 在一個無向圖中,如果一個頂點子集滿足子集內(nèi)的任意兩個不同頂點之間都是相連的,那么這個頂點子集就被稱為一個團。
  • 如果一個團不能通過加入某個新的頂點來擴展成一個更大的團,那么該團就被稱為最大團。
  • 現(xiàn)在,你需要判斷給定頂點子集能否構(gòu)成一個最大團。
#include <iostream> #include <cstring> using namespace std;const int N = 210;int n, m; bool g[N][N]; int nodes[N], cnt; bool st[N];bool check_clique() {for (int i = 0; i < cnt; i ++ )for (int j = 0; j < i; j ++ )if (!g[nodes[i]][nodes[j]])return false;return true; }bool check_maximum() {memset(st, 0, sizeof st);for (int i = 0; i < cnt; i ++ )st[nodes[i]] = true;for (int i = 1; i <= n; i ++ ){if (!st[i]){bool success = false;for (int j = 0; j < cnt; j ++ )if (!g[i][nodes[j]]){success = true;break;}if (!success) return false;}}return true; }int main() {scanf("%d%d", &n, &m);int a, b;while (m -- ){scanf("%d%d", &a, &b);g[a][b] = g[b][a] = true;}int k; scanf("%d", &k);while (k -- ){scanf("%d", &cnt);for (int i = 0; i < cnt; i ++ ) scanf("%d", &nodes[i]);if (check_clique()){if (check_maximum()) puts("Yes");else puts("Not Maximal");}elseputs("Not a Clique");} }

1146 Topological Order (25 分)

題意 :

  • 以下哪個選項不是從給定的有向圖中獲得的拓撲序列?
  • 現(xiàn)在,請你編寫一個程序來測試每個選項。

思路 :

  • 將輸入的每一條邊存下來
  • 對于每對詢問,遍歷每條邊,如果邊的起點比邊的終點在詢問中出現(xiàn)的位置晚,說明詢問不合格

語法 :

  • is_first的使用,如果是true,將其轉(zhuǎn)為false;否則輸出空格
#include <iostream> #include <cstring>using namespace std;const int N = 1010, M = 10010;int n, m; struct Edge {int a, b; }e[M]; int p[N];int main() {cin >> n >> m;for (int i = 0; i < m; i ++ ) cin >> e[i].a >> e[i].b;int k;cin >> k;bool is_first = true;for (int i = 0; i < k; i ++ ){for (int j = 1; j <= n; j ++ ){int x;cin >> x;p[x] = j;}bool success = true;for (int j = 0; j < m; j ++ )if (p[e[j].a] > p[e[j].b]){success = false;break;}if (!success){if (is_first) is_first = false;else cout << ' ';cout << i;}}cout << endl;return 0; }

1150 Travelling Salesman Problem (25 分)

思路 :

  • 如果所給的路徑中不連通,success為false,sum為-1,輸出NA;如果第一個點和最后一個不是同一個點,沒有遍歷所有點;遍歷完路徑后,如果有點沒有被路徑包含,則success為false,輸出不是一個訪問了所有城市的回路;
  • 如果路徑點的數(shù)量等于n+1,說明是簡單回路,否則就不是簡單回路
  • 然后動態(tài)維護最小距離和最小距離的組號
  • 無向帶權(quán)圖,因此初始化距離為正無窮
  • 用sum表示路徑和,如果是-1,說明無法計算;success表示是否是否訪問了所有城市
#include <iostream> #include <cstring>using namespace std;const int N = 210, INF = 0x3f3f3f3f;int n, m; int d[N][N], vers[310]; bool st[N];int main() {cin >> n >> m;memset(d, 0x3f, sizeof d);for (int i = 0; i < m; i ++ ){int a, b, c;cin >> a >> b >> c;d[a][b] = d[b][a] = c;}int k;cin >> k;int min_dist = INF, min_id;for (int T = 1; T <= k; T ++ ){int cnt;cin >> cnt;for (int i = 0; i < cnt; i ++ ) cin >> vers[i];int sum = 0;bool success = true;memset(st, 0, sizeof st);for (int i = 0; i + 1 < cnt; i ++ ){int a = vers[i], b = vers[i + 1];if (d[a][b] == INF){sum = -1;success = false;break;}else sum += d[a][b];st[a] = true;}for (int i = 1; i <= n; i ++ )if (!st[i]){success = false;break;}if (vers[0] != vers[cnt - 1]) success = false;if (sum == -1) printf("Path %d: NA (Not a TS cycle)\n", T);else{if (!success) printf("Path %d: %d (Not a TS cycle)\n", T, sum);else{if (cnt == n + 1) printf("Path %d: %d (TS simple cycle)\n", T, sum);else printf("Path %d: %d (TS cycle)\n", T, sum);if (min_dist > sum){min_dist = sum;min_id = T;}}}}printf("Shortest Dist(%d) = %d\n", min_id, min_dist);return 0; }

1154 Vertex Coloring (25 分)

題意 :

  • 一個合適的頂點著色是指用各種顏色標記圖中各個頂點,使得每條邊的兩個端點的顏色都不相同。
  • 如果一種合適的頂點著色方案使用了一共 k 種不同的顏色,則稱其為合適的 k 著色(k-coloring)。
  • 現(xiàn)在,你需要判斷給定的著色方案是否是合適的 k 著色方案。

思路 :

  • 用結(jié)構(gòu)體存邊
  • 對于每一個詢問,首先遍歷所有邊,如果所有邊的顏色都沒有出現(xiàn)矛盾,再判斷顏色數(shù)量是否是k種
#include <iostream> #include <cstring> #include <unordered_set>using namespace std;const int N = 10010;int n, m; struct Edge {int a, b; }e[N]; int color[N];int main() {cin >> n >> m;for (int i = 0; i < m; i ++ ) cin >> e[i].a >> e[i].b;int k;cin >> k;while (k -- ){for (int i = 0; i < n; i ++ ) cin >> color[i];bool success = true;for (int i = 0; i < m; i ++ )if (color[e[i].a] == color[e[i].b]){success = false;break;}if (success){unordered_set<int> S;for (int i = 0; i < n; i ++ ) S.insert(color[i]);printf("%d-coloring\n", S.size());}else puts("No");}return 0; } 與50位技術(shù)專家面對面20年技術(shù)見證,附贈技術(shù)全景圖

總結(jié)

以上是生活随笔為你收集整理的PAT甲级题目翻译+答案 AcWing(图论)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。