Loading [MathJax]/extensions/tex2jax.js

P1841:「JSOI2007」重要的城市题解

思路

这道题是lornd巨佬给我写的。由于我太菜了,只能放弃看题解。看完题解之后,发现解法甚是巧妙,便来分享一则。

原理就是在无向图floyed求最短路的时候,每发现一次新的路径就要更新一次重要点。策略如下:

  1. 如果原路径比现在的路径要长,那么更新路径,并且在cities[i][j]中记录点k。
  2. 如果原路径和现在的路径相等,那么重要点不唯一,那么把cities[i][j]记录为-1。

最终在cities里面搜索不为-1的元素,排序输出即可。

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// P1841.cpp
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
#define ll long long
ll mat[300][300];
int dp[300][300];
bool ans[500];
const ll INF = (ll)(0x7fffffff) / 3;
int n, m;
void floyed()
{
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
if (i != k)
for (int j = 1; j <= n; j++)
if (i != j && j != k)
if (mat[i][k] + mat[k][j] < mat[i][j])
mat[i][j] = mat[i][k] + mat[k][j], dp[i][j] = k;
else if (mat[i][k] + mat[k][j] == mat[i][j])
dp[i][j] = -1;
}
void addpath(int src, int dst, ll w)
{
mat[src][dst] = mat[dst][src] = w;
}
int main()
{
fill(mat[0], mat[0] + 300 * 300, INF);
cin >> n >> m;
for (int i = 0; i < m; i++)
{
ll a, b, c;
cin >> a >> b >> c;
addpath(a, b, c);
}
floyed();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (dp[i][j] != -1)
ans[dp[i][j]] = true;
bool flag = true;
for (int i = 1; i <= n; i++)
if (ans[i])
cout << i << " ", flag = false;
if (flag)
cout << "No important cities.";
return 0;
}
// P1841.cpp #include <iostream> #include <algorithm> #include <vector> using namespace std; #define ll long long ll mat[300][300]; int dp[300][300]; bool ans[500]; const ll INF = (ll)(0x7fffffff) / 3; int n, m; void floyed() { for (int k = 1; k <= n; k++) for (int i = 1; i <= n; i++) if (i != k) for (int j = 1; j <= n; j++) if (i != j && j != k) if (mat[i][k] + mat[k][j] < mat[i][j]) mat[i][j] = mat[i][k] + mat[k][j], dp[i][j] = k; else if (mat[i][k] + mat[k][j] == mat[i][j]) dp[i][j] = -1; } void addpath(int src, int dst, ll w) { mat[src][dst] = mat[dst][src] = w; } int main() { fill(mat[0], mat[0] + 300 * 300, INF); cin >> n >> m; for (int i = 0; i < m; i++) { ll a, b, c; cin >> a >> b >> c; addpath(a, b, c); } floyed(); for (int i = 1; i <= n; i++) for (int j = 1; j <= n; j++) if (dp[i][j] != -1) ans[dp[i][j]] = true; bool flag = true; for (int i = 1; i <= n; i++) if (ans[i]) cout << i << " ", flag = false; if (flag) cout << "No important cities."; return 0; }
// P1841.cpp
#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;
#define ll long long
ll mat[300][300];
int dp[300][300];
bool ans[500];
const ll INF = (ll)(0x7fffffff) / 3;
int n, m;

void floyed()
{
    for (int k = 1; k <= n; k++)
        for (int i = 1; i <= n; i++)
            if (i != k)
                for (int j = 1; j <= n; j++)
                    if (i != j && j != k)
                        if (mat[i][k] + mat[k][j] < mat[i][j])
                            mat[i][j] = mat[i][k] + mat[k][j], dp[i][j] = k;
                        else if (mat[i][k] + mat[k][j] == mat[i][j])
                            dp[i][j] = -1;
}

void addpath(int src, int dst, ll w)
{
    mat[src][dst] = mat[dst][src] = w;
}

int main()
{
    fill(mat[0], mat[0] + 300 * 300, INF);
    cin >> n >> m;
    for (int i = 0; i < m; i++)
    {
        ll a, b, c;
        cin >> a >> b >> c;
        addpath(a, b, c);
    }
    floyed();
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (dp[i][j] != -1)
                ans[dp[i][j]] = true;
    bool flag = true;
    for (int i = 1; i <= n; i++)
        if (ans[i])
            cout << i << " ", flag = false;
    if (flag)
        cout << "No important cities.";
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *