愚人节快乐!
下午,进行了一个课的上。
图论选讲。
然后写了两题。
T1.飞行路线(分层图板题)
题目说可以有k次机会不花钱。
那么我们就可以分层图,跑djikstra。(具体建图看代码注释)
code:
#include<bits/stdc++.h>
//#define int long long
#define debug puts("hwl");
using namespace std;
const int N = 1e5 + 10, M = 2e6 + 10;
vector<pair<int, int> > v[M];
bool vis[M];
int dis[M];
void dijkstra(int s){
memset(dis, 0x3f, sizeof dis);
priority_queue<pair<int, int> > q;
q.push({0, s});
dis[s] = 0;
while(!q.empty()){
auto e1 = q.top();
q.pop();
int x = e1.second;
if(vis[x]) continue;
vis[x] = 1;
for(auto e : v[x]){
int y = e.first, w = e.second;
if(vis[y]) continue;
if(dis[y] > dis[x] + w){
dis[y] = dis[x] + w;
q.push({-dis[y], y});
}
}
}
return;
}
int main() {
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, m, k, s, t;
cin >> n >> m >> k >> s >> t;
for(int i = 1; i <= m; i++){
int x, y, w;
cin >> x >> y >> w;
v[x].push_back({y, w});
v[y].push_back({x, w});
for(int j = 1; j <= k; j++){
v[x + (j - 1) * n].push_back({y + j * n, 0});
v[y + (j - 1) * n].push_back({x + j * n, 0});
v[x + j * n].push_back({y + j * n, w});
v[y + j * n].push_back({x + j * n, w});
}//这里为什么这样建边 我的理解
/*
首先x和y之间有一条边权为w的边。
我们可以选择分层图。
每次层数低的只能向刚好比它层数高一的连边。
低的x向高的y连一条边权为0的边,同时低的y向高的x连一条边权为0的边。
同一层的x,y连长度为w的边。
到最高的那一层就表示我们“免费”次数用完了。
*/
}
dijkstra(s);
int ans = 0x3f3f3f3f;
for(int i = 0; i <= k; i++)
ans = min(ans, dis[t + i * n]);
cout << ans << endl;
return 0;
}//by hwl
T2.The Captain
可以飞快地想到O(n^2)的做法。
但是这会TLE,那怎么办?
可以发现我们建的那么多边很多都是无用的。
我们发现假设(x1,y1)和(x2,y2)之间(之间可以理解为它们形成的长方形中的某一点)有一点。
那么我们从中间这样间接过来一定比直接过去要优。(可以画画图手玩一下)
所以只需要分别按x,y排序。
然后分别将相邻的点连边,跑dijkstra即可。
#include<bits/stdc++.h>
#define int long long
#define debug puts("hwl");
using namespace std;
const int N = 2e5 + 10;
struct Date{
int x, y, idx;
}p[N];
vector<pair<int, int>> v[N];
bool cmp1(Date a, Date b){
return a.x < b.x;
}
bool cmp2(Date a, Date b){
return a.y < b.y;
}
bool vis[N];
int dis[N];
void dijkstra(int s){
memset(dis, 0x3f, sizeof dis);
dis[s] = 0;
priority_queue<pair<int, int>> q;
q.push({0, s});
while(!q.empty()){
auto now = q.top();
q.pop();
int x = now.second;
if(vis[x]) continue;
vis[x] = 1;
for(auto e : v[x]){
int y = e.first, w = e.second;
if(vis[y]) continue;
if(dis[y] > dis[x] + w){
dis[y] = dis[x] + w;
q.push({-dis[y], y});
}
}
}
return;
}
signed main() {
// freopen(".in", "r", stdin);
// freopen(".out", "w", stdout);
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n;
cin >> n;
for(int i = 1; i <= n; i++){
int x, y;
cin >> x >> y;
p[i] = Date{x, y, i};
}
sort(p + 1, p + 1 + n, cmp1);
for(int i = 1; i < n; i++){
int j = i + 1;
int x1 = p[i].x ,y1 = p[i].y, x2 = p[j].x, y2 = p[j].y;
v[p[i].idx].push_back({p[j].idx, min(abs(x1 - x2), abs(y1 - y2))});
v[p[j].idx].push_back({p[i].idx, min(abs(x1 - x2), abs(y1 - y2))});
}
sort(p + 1, p + 1 + n, cmp2);
for(int i = 1; i < n; i++){
int j = i + 1;
int x1 = p[i].x ,y1 = p[i].y, x2 = p[j].x, y2 = p[j].y;
v[p[i].idx].push_back({p[j].idx, min(abs(x1 - x2), abs(y1 - y2))});
v[p[j].idx].push_back({p[i].idx, min(abs(x1 - x2), abs(y1 - y2))});
}
dijkstra(1);
cout << dis[n] << endl;
return 0;
}//by hwl
晚上,正在进行中。。。