分层图模板题
作者:互联网
感谢所有AC
分层图形式
传送门
思路
建立分层图,即复制 $k + 1$ 张图,层与层之间建立零权边。对源点进行 $dijstra$ ,得出源点到分层图上任意一点的最短路。由于最优方案并非要把所有次数用完,所以最后需要取终点的所有可能的最小值。需要注意空间大小,如果数据过大无法使用。
该题为模板题,无特殊。
代码
#include<iostream>
#include<cstring>
#include<queue>
#define maxn 50050
using namespace std;
struct edge {
int to, val, nxt;
}g[maxn*44];
struct node {
int s, w;
bool operator<(const node& a)const {
if (w != a.w)return w > a.w;
else return s < a.s;
}
};
priority_queue<node> q;
int cnt, hd[maxn*11], dis[maxn * 11], u, v, w, n, m, s, t, k, ans = INT32_MAX;
bool vis[maxn * 11];
void add(int u, int v, int w)
{
g[++cnt].val = w;
g[cnt].to = v;
g[cnt].nxt = hd[u];
hd[u] = cnt;
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m >> k >> s >> t;
for (int i = 1; i <= m; i++)
{
cin >> u >> v >> w;
add(u, v, w);
add(v, u, w);
for (int j = 1; j <= k; j++)
{
add(u + j * n, v + j * n, w);
add(v + j * n, u + j * n, w);
add(u + j * n - n, v + j * n, 0);
add(v + j * n - n, u + j * n, 0);
}
}
memset(dis, 63, sizeof(dis));
dis[s] = 0;
q.push({ s,0 });
while (!q.empty())
{
int u = q.top().s;
q.pop();
if (vis[u])continue;
vis[u] = true;
for (int i = hd[u]; i; i = g[i].nxt)
if (dis[g[i].to] > dis[u] + g[i].val && !vis[g[i].to])
{
dis[g[i].to] = dis[u] + g[i].val;
q.push({ g[i].to,dis[g[i].to] });
}
}
for (int i = 0; i <= k; i++)
ans = min(ans, dis[t + i * n]);
cout << ans;
return 0;
}
DP形式
传送门
思路
DP思想,定义状态 $f(i,j)$ 为到达点 $i$ ,花费 $j$ 次机会的最短路径。在优先队列中多加入一个 $cost$ 的变量来限制使用机会的次数。在松弛操作中比朴素的 $dijstra$ 要多一个使用一次机会的情况。对空间的要求比分层图小得多,可以优先考虑。
该题为 $dijstra$ 的变种,最短路径是整条路径的最大权值,在松弛时需要拿当前路径和两点间权值的最大值来操作。
代码
#include<iostream>
#include<queue>
#include<cstring>
#define maxn 1007
using namespace std;
struct edge {
int to, val, nxt;
}g[maxn*20];
struct node {
int s, c;
long long w;
bool operator <(const node& a)const {
return w > a.w;
}
};
int hd[maxn], cnt, n, m, k, u, v, w;
bool vis[maxn][maxn];
long long dis[maxn][maxn];
priority_queue<node> q;
void add(int u, int v, int w)
{
g[++cnt].val = w;
g[cnt].to = v;
g[cnt].nxt = hd[u];
hd[u] = cnt;
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> n >> m >> k;
for (int i = 1; i <= m; i++)
{
cin >> u >> v >> w;
add(u, v, w);
add(v, u, w);
}
memset(dis, 64, sizeof(dis));
dis[1][0] = 0;
q.push({ 1,0,0 });
long long ans = dis[0][0];
while (!q.empty())
{
int u = q.top().s, cost = q.top().c;
q.pop();
if (vis[u][cost])continue;
vis[u][cost] = true;
for (int i = hd[u]; i; i = g[i].nxt)
{
int v = g[i].to;
if (dis[v][cost] > max((long long)g[i].val,dis[u][cost]) && !vis[v][cost])
{
dis[v][cost] = max((long long)g[i].val,dis[u][cost]);
q.push({ v, cost, dis[v][cost] });
}
if (dis[v][cost + 1] > dis[u][cost] && cost < k && !vis[v][cost + 1])
{
dis[v][cost + 1] = dis[u][cost];
q.push({ v,cost + 1,dis[v][cost + 1] });
}
}
}
for (int i = 0; i <= k; i++)
ans = min(ans, dis[n][i]);
if (ans == dis[0][0])cout << -1;
else cout << ans;
return 0;
}
标签:cnt,int,long,分层,cost,maxn,模板,dis 来源: https://www.cnblogs.com/xqk0225/p/16209221.html