Code:
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
typedef long long ll;
constexpr int max_n = 1200, max_tn = 1000, max_c = 50000;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
struct node
{
int id, vl;
node(int _i = 0, int _v = 0) : id(_i), vl(_v) { }
bool operator<(const node& n) const
{
return vl > n.vl;
}
};
priority_queue<node> pq;
ll g[max_n+1][max_n+1], dis[max_n+1];
int btw[max_tn+1];
bool vis[max_n+1];
inline ll my_min(ll a, ll b) { return (a < b)? a:b; }
inline int my_max(int a, int b) { return (a > b)? a:b; }
int main()
{
memset(g, 0x3f, sizeof g);
memset(dis, 0x3f, sizeof dis);
ios_base::sync_with_stdio(false);
cin.tie(0);
int s, t, n, cnt = 0;
ll tc;
node cur;
cin >> s >> t >> n;
for (int ii = 0, tn; ii < n; ii++)
{
cin >> tc >> tn;
for (int i = 0; i < tn; i++)
{
cin >> btw[i];
for (int j = 0; j < i; j++)
{
g[btw[j]][btw[i]] = my_min(g[btw[j]][btw[i]], (1ll * max_c * tc) + i - j);
}
cnt = my_max(cnt, btw[i]);
}
}
// fprintf(stderr, "%lld\n", cnt);
/*
for (int i = 1; i < 100; i++)
for (int j = 1; j < 100; j++)
if (g[i][j] != INF)
fprintf(stderr, "%d %d %lld %lld %lld\n", i, j, g[i][j] / max_c, g[i][j] % max_c, g[i][j]);
*/
dis[s] = 0;
pq.emplace(s, 0);
while (!pq.empty())
{
cur = pq.top();
pq.pop();
if (!vis[cur.id])
{
vis[cur.id] = true;
for (int i = 1; i <= cnt; i++) if (i != cur.id)
if (dis[i] > dis[cur.id] + g[cur.id][i])
{
dis[i] = dis[cur.id] + g[cur.id][i];
pq.emplace(i, dis[i]);
}
}
}
if (dis[t] == INF)
cout << "-1 -1" << endl;
else
cout << dis[t] / max_c << " " << dis[t] % max_c << endl;
return 0;
}
做法就是最短路,然后用了个技巧:将边权赋为实际权值*大常数+经过城市数。WA on #10。
反复测试后,发现输出答案与上文大常数(即max_c
)有关,5000时最接近答案。不知道哪里有问题,自闭了,求调/kel。