原題:
https://cses.fi/problemset/task/1672
題意:
給定 n 個點、m 條有向邊、q 個查詢。每個查詢問 a→b 的最短距離;若不可達輸出 -1。
解題思路:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m, q;
cin >> n >> m >> q;
const long long INF = (long long)4e18;
vector<vector<long long>> dist(n+1, vector<long long>(n+1, INF));
for (int i = 1; i <= n; ++i) dist[i][i] = 0;
for (int i = 0; i < m; ++i) {
int a, b; long long w;
cin >> a >> b >> w;
dist[a][b] = min(dist[a][b], w); // 處理多重邊
}
for (int k = 1; k <= n; ++k) {
for (int i = 1; i <= n; ++i) if (dist[i][k] < INF) {
for (int j = 1; j <= n; ++j) if (dist[k][j] < INF) {
long long nd = dist[i][k] + dist[k][j];
if (nd < dist[i][j]) dist[i][j] = nd;
}
}
}
while (q--) {
int a, b; cin >> a >> b;
long long ans = dist[a][b];
cout << (ans >= INF/2 ? -1 : ans) << "\n";
}
return 0;
}
原題:
https://cses.fi/problemset/task/1678
題意:
給一張有向圖,若存在有向環,輸出該環的節點序列;否則輸出 IMPOSSIBLE。
解題思路:
#include <bits/stdc++.h>
using namespace std;
int main(){
cin >> n >> m;
vector<vector<int>> g(n+1);
for(int i=0;i<m;i++){
int u,v; cin >> u >> v;
g[u].push_back(v);
}
vector<int> color(n+1,0), parent(n+1,-1);
int cyc_u=-1, cyc_v=-1;
function<bool(int)> dfs = [&](int u){
color[u]=1;
for(int v: g[u]){
if(color[v]==0){
parent[v]=u;
if(dfs(v)) return true;
}else if(color[v]==1){
cyc_u=u; cyc_v=v; // 發現回邊 u->v
return true;
}
}
color[u]=2;
return false;
};
for(int i=1;i<=n;i++){
if(color[i]==0 && dfs(i)){
// 重建環 v ... u -> v
vector<int> cyc; cyc.push_back(cyc_v);
for(int x=cyc_u; x!=cyc_v; x=parent[x]) cyc.push_back(x);
cyc.push_back(cyc_v);
reverse(cyc.begin(), cyc.end());
cout << cyc.size() << "\n";
for(size_t k=0;k<cyc.size();k++)
cout << cyc[k] << (k+1==cyc.size()?'\n':' ');
return 0;
}
}
cout << "IMPOSSIBLE\n";
return 0;
}
原題:
https://leetcode.com/problems/cheapest-flights-within-k-stops/description/
題意:
城市 n、航線 flights[u,v,w],從 src 飛到 dst,最多 K 次中轉(即最多 K+1 段航班)。求最小成本,不能到達回傳 -1。
解題思路:
class Solution {
public:
int findCheapestPrice(int n, vector<vector<int>>& flights, int src, int dst, int K) {
const int INF = 1e9;
vector<int> dist(n, INF);
dist[src] = 0;
// 允許最多 K 次中轉 → 最多 K+1 段邊
for (int t = 0; t <= K; ++t) {
vector<int> nd = dist; // 只用上一輪結果
for (auto &e: flights) {
int u = e[0], v = e[1], w = e[2];
if (dist[u] == INF) continue;
nd[v] = min(nd[v], dist[u] + w);
}
dist.swap(nd);
}
return dist[dst] >= INF/2 ? -1 : dist[dst];
}
};
題意:
給定無向加權圖與門檻 distanceThreshold。對每個城市 i,計算所有 dist[i][j] <= threshold 的城市數量(不含自己),回傳 鄰居數最少 的城市;若有多個,回傳 索引較大 的那個。
解題思路:
class Solution {
public:
int findTheCity(int n, vector<vector<int>>& edges, int threshold) {
const int INF = 1e9;
vector<vector<int>> dist(n, vector<int>(n, INF));
for (int i = 0; i < n; ++i) dist[i][i] = 0;
for (auto &e: edges) {
int u=e[0], v=e[1], w=e[2];
dist[u][v] = min(dist[u][v], w);
dist[v][u] = min(dist[v][u], w);
}
for (int k = 0; k < n; ++k)
for (int i = 0; i < n; ++i) if (dist[i][k] < INF)
for (int j = 0; j < n; ++j) if (dist[k][j] < INF)
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);
int bestCity = -1, bestCnt = INT_MAX;
for (int i = 0; i < n; ++i) {
int cnt = 0;
for (int j = 0; j < n; ++j)
if (i != j && dist[i][j] <= threshold) cnt++;
// 鄰居數更少,或平手取索引較大
if (cnt < bestCnt || (cnt == bestCnt && i > bestCity)) {
bestCnt = cnt; bestCity = i;
}
}
return bestCity;
}
};