关于最短路
最短路
1. Sightseeing Trip
/*
Time: 1.3
Worker: Blank_space
Source: #10072. 「一本通 3.2 例 1」Sightseeing Trip
最小环 tarjan
挂了 写个鬼tarjan
floyd不好吗
输出有毒:No solution. —— 最后面还有个点
还是挂。。。
开个long long 试试
还是挂
(ll)dis[i][j] + mp[i][k] + mp[k][j]
好吧 确实就是 long long 的问题
*/
/*--------------------------------------------*/
#include<cstdio>
#include<string.h>
#include<algorithm>
#define ll long long
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int n, m, mp[110][110], dis[110][110], _min = INF, cnt, pre[110][110], path[110];
bool vis[110];
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
/*----------------------------------------函数*/
signed main()
{
n = read(); m = read();
memset(dis, 0x3f, sizeof dis);
memset(mp, 0x3f, sizeof mp);
for(int i = 1; i <= m; i++)
{
int x = read(), y = read(), z = read();
mp[x][y] = mp[y][x] = mp[x][y] ? min(mp[x][y], z) : z;
dis[x][y] = dis[y][x] = mp[x][y];
}
for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) pre[i][j] = i;
for(int k = 1; k <= n; k++)
{
for(int i = 1; i < k; i++)
for(int j = i + 1; j < k; j++)
if((ll)dis[i][j] + mp[i][k] + mp[k][j] < _min)
{
_min = dis[i][j] + mp[i][k] + mp[k][j];
int t = j; cnt = 0;
while(t != i) path[++cnt] = t, t = pre[i][t];
path[++cnt] = i; path[++cnt] = k;
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(dis[i][j] > dis[i][k] + dis[k][j])
{dis[i][j] = dis[i][k] + dis[k][j]; pre[i][j] = pre[k][j];}
}
if(!cnt) {puts("No solution."); return 0;}
for(int i = 1; i <= cnt; i++) printf("%d ", path[i]);
return 0;
}
2. 孤岛营救问题
/*
Time: 1.3
Worker: Blank_space
Source: #6121. 「网络流 24 题」孤岛营救问题
网络流??? 吓死
初步:分层图 p 只有 10
n m 比较小 可以瞎搞
发现不会建图... 跑bfs
RE ???
一段时间的修码...
数据有毒啊 一个格子里面可以有多把钥匙
*/
/*--------------------------------------------*/
#include<cstdio>
#include<queue>
#include<string.h>
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int n, m, p, k, s, mp[20][20][20][20], key[20][20];
int dx[5] = {0, 1, -1, 0, 0};
int dy[5] = {0, 0, 0, 1, -1};
bool vis[20][20][1 << 12];
struct node {
int x, y, key, dis;
};
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
int bfs()
{
queue <node> q;
q.push((node){1, 1, 0 | key[0][0], 0});
vis[1][1][0 | key[1][1]] = 1;
while(!q.empty())
{
node t = q.front(); q.pop();
node g;
for(int i = 1; i <= 4; i++)
{
g.x = t.x + dx[i], g.y = t.y + dy[i];
if(g.x < 1 || g.x > n || g.y < 1 || g.y > m || mp[t.x][t.y][g.x][g.y] == 0) continue;
if(mp[t.x][t.y][g.x][g.y] == -1 || (t.key & mp[t.x][t.y][g.x][g.y]))
{
if(!key[g.x][g.y]) g.key = t.key;
else g.key = t.key | key[g.x][g.y];
if(vis[g.x][g.y][g.key]) continue;
vis[g.x][g.y][g.key] = 1;
g.dis = t.dis + 1;
q.push(g);
if(g.x == n && g.y == m) return g.dis;
}
}
}
return -1;
}
/*----------------------------------------函数*/
int main()
{
// freopen("rescue4.in", "r", stdin);
n = read(); m = read(); p = read(); k = read();
memset(mp, -1, sizeof mp);
for(int i = 1; i <= k; i++)
{
int x1 = read(), y1 = read(), x2 = read(), y2 = read(), opt = read();
mp[x1][y1][x2][y2] = mp[x2][y2][x1][y1] = opt ? 1 << opt - 1 : opt;
}
s = read();
for(int i = 1; i <= s; i++)
{
int x = read(), y = read(), opt = read();
key[x][y] |= 1 << opt - 1;
}
printf("%d\n", bfs());
return 0;
}
3. 架设电话线
/*
Time: 1.17
Worker: Blank_space
Source: #10074. 「一本通 3.2 例 3」架设电话线
二分答案 转换为 01 图 双端队列bfs 或者 最短路就随意了
与 k 比较 验证答案即可
*/
/*--------------------------------------------*/
#include<cstdio>
#include<cstring>
#include<queue>
#define ll long long
#define emm(x, a) memset(x, a, sizeof x)
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*------------------------------------常量定义*/
ll n, p, k, mx, ans, dis[1010];
bool flag, vis[1010];
struct node {
int u, v, w;
}a[2010];
struct edge {
int v, w, nxt;
}e[4010];
int head[1010], js;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
int max(int x, int y) {return x > y ? x : y;}
void add_edge(int u, int v, int w){e[++js].v = v; e[js].w = w; e[js].nxt = head[u]; head[u] = js;}
bool check(int x)
{
emm(head, 0); emm(e, 0); emm(vis, 0); js = 0;
for(int i = 1; i <= n; i++) dis[i] = 1e15;
for(int i = 1; i <= p; i++)
{
bool op = 0;
if(a[i].w > x) op = 1;
add_edge(a[i].u, a[i].v, op);
add_edge(a[i].v, a[i].u, op);
}
deque <int> q;
q.push_front(1); dis[1] = 0;
while(!q.empty())
{
int u = q.front(); q.pop_front();
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u]; i; i = e[i].nxt)
{
ll v = e[i].v, w = e[i].w;
dis[v] = min(dis[v], dis[u] + w);
if(w) q.push_back(v);
else q.push_front(v);
}
}
if(dis[n] == 1e15) flag = 1;
return dis[n] <= k;
}
/*----------------------------------------函数*/
int main()
{
// freopen("phoneline.7.in","r",stdin);
// freopen(".out","w",stdout);
n = read(); p = read(); k = read();
for(int i = 1; i <= p; i++) a[i].u = read(), a[i].v = read(), a[i].w = read(), mx = max(mx, a[i].w);
int l = 0, r = mx;
while(l <= r)
{
if(flag) {puts("-1"); return 0;}
int mid = (l + r) >> 1;
if(check(mid)) {r = mid - 1; ans = mid;}
else l = mid + 1;
}
printf("%lld", ans);
// fclose(stdin);
// fclose(stdout);
return 0;
}
4. 农场派对
/*
Time: 1.17
Worker: Blank_space
Source: #10075. 「一本通 3.2 练习 1」农场派对
去的时候建反图 跑最短路
回来的时候直接跑最短路
*/
/*--------------------------------------------*/
#include<cstdio>
#include<cstring>
#include<queue>
#define ll long long
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*------------------------------------常量定义*/
int n, m, s;
ll dis[2][1010], ans;
bool vis[2][1010];
struct edge {
int v, nxt;
ll w;
}e[2][B];
int head[2][1010], js;
/*------------------------------------变量定义*/
inline ll read() {
ll x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
ll max(ll x, ll y) {return x > y ? x : y;}
void add_edge(int u, int v, ll w, int opt)
{
e[opt][++js].v = v; e[opt][js].w = w;
e[opt][js].nxt = head[opt][u]; head[opt][u] = js;
}
void SPFA(int opt)
{
queue <int> q;
memset(dis[opt], 0x3f, sizeof dis[opt]);
q.push(s); dis[opt][s] = 0; vis[opt][s] = 1;
while(!q.empty())
{
int u = q.front(); q.pop(); vis[opt][u] = 0;
for(int i = head[opt][u]; i; i = e[opt][i].nxt)
{
int v = e[opt][i].v; ll w = e[opt][i].w;
if(dis[opt][v] <= dis[opt][u] + w) continue;
dis[opt][v] = dis[opt][u] + w;
if(!vis[opt][v]) {q.push(v); vis[opt][v] = 1;}
}
}
}
/*----------------------------------------函数*/
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n = read(); m = read(); s = read();
for(int i = 1; i <= m; i++)
{
int x = read(), y = read(), z = read();
add_edge(x, y, z, 0); add_edge(y, x, z, 1);
}
SPFA(0);
SPFA(1);
for(int i = 1; i <= n; i++)
ans = max(ans, dis[0][i] + dis[1][i]);
printf("%lld", ans);
// fclose(stdin);
// fclose(stdout);
return 0;
}
5. Roadblocks
/*
Time: 1.17
Worker: Blank_space
Source: #10076. 「一本通 3.2 练习 2」Roadblocks
严格次短路
*/
/*--------------------------------------------*/
#include<cstdio>
#include<queue>
#include<cstring>
#define emm(x) memset(x, 0x3f, sizeof x)
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*------------------------------------常量定义*/
int n, r, d[5010], c[5010];
bool vis[5010];
struct edge {
int v, w, nxt;
}e[B << 1];
int head[5010], js;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void add_edge(int u, int v, int w) {e[++js].v = v; e[js].w = w; e[js].nxt = head[u]; head[u] = js;}
/*----------------------------------------函数*/
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n = read(); r = read();
for(int i = 1; i <= r; i++)
{
int x = read(), y = read(), z = read();
add_edge(x, y, z); add_edge(y, x, z);
}
queue <int> q; emm(d); emm(c);
q.push(1); d[1] = 0;
while(!q.empty())
{
int u = q.front(); q.pop(); vis[u] = 0;
for(int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].v, w = e[i].w; bool p = 0;
if(d[v] > d[u] + w) c[v] = d[v], d[v] = d[u] + w, p = 1;
if(c[v] > c[u] + w) c[v] = c[u] + w, p = 1;
if(d[v] < d[u] + w && d[u] + w < c[v]) c[v] = d[u] + w, p = 1;
if(p && !vis[v]) {vis[v] = 1; q.push(v);}
}
}
printf("%d", c[n]);
// fclose(stdin);
// fclose(stdout);
return 0;
}
6. 最短路计数
/*
Time: 1.17
Worker: Blank_space
Source: #10077. 「一本通 3.2 练习 3」最短路计数
如题目:最短路计数
*/
/*--------------------------------------------*/
#include<cstdio>
#include<queue>
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 100003;
const int INF = 0x3f3f3f3f;
/*------------------------------------常量定义*/
int n, m, dep[B], f[B];
bool vis[B];
struct edge {
int v, nxt;
}e[B << 2];
int head[B], js;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void add_edge(int u, int v) {e[++js].v = v; e[js].nxt = head[u]; head[u] = js;}
/*----------------------------------------函数*/
int main()
{
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
n = read(); m = read();
for(int i = 1; i <= m; i++) {int x = read(), y = read(); add_edge(x, y); add_edge(y, x);}
queue <int> q;
q.push(1); dep[1] = 0; vis[1] = 1; f[1] = 1;
while(!q.empty())
{
int u = q.front(); q.pop();
for(int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].v;
if(!vis[v]) {dep[v] = dep[u] + 1; vis[v] = 1; q.push(v);}
if(dep[v] == dep[u] + 1) f[v] = (f[u] + f[v]) % mod;
}
}
for(int i = 1; i <= n; i++) printf("%d\n", f[i]);
// fclose(stdin);
// fclose(stdout);
return 0;
}
7. 新年好
/*
Time: 1.17
Worker: Blank_space
Source: #10078. 「一本通 3.2 练习 4」新年好
好在他家亲戚少...
直接把最短路跑了 暴力枚举全排列 5! = 120
时间还是吃的起的
(听说这个题的数据卡 SPFA ?)
然后我写了个 dijkstra 所以我 T 了...
数据卡常啊
这件事情告诉我们 以后写 dijk 要加剪枝
发现好像剪枝不是主要问题 似乎是我写的 dijk 常数太大了
不行了... 调了两个小时 还是 T
重构...
感觉邻接表加边好像要慢?? 以后不写邻接表了
*/
/*--------------------------------------------*/
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#define emm(x) memset(x, 0x3f, sizeof x)
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
/*------------------------------------常量定义*/
typedef pair <int, int> P;
struct edge {
int v, w;
};
std::vector<edge> G[50010];
int n, m, a[7], dis[7][50010], ans = INF;
bool vis[7];
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
void add_edge(int u, int v, int w)
{
G[u].push_back((edge){v, w});
G[v].push_back((edge){u, w});
}
void dijk(int s)
{
priority_queue<P, vector<P>, greater<P> > q;
dis[s][a[s]] = 0;
q.push(P(0, a[s]));
while(!q.empty())
{
P p = q.top();
q.pop();
int u = p.second;
if(p.first > dis[s][u]) continue;
for(int i = 0; i < G[u].size(); i++)
{
edge e = G[u][i];
if(dis[s][e.v] > dis[s][u] + e.w)
{
dis[s][e.v] = dis[s][u] + e.w;
q.push(P(dis[s][e.v], e.v));
}
}
}
}
void dfs(int t, int sum, int per)
{
if(sum > ans) return ;
if(t == 5) {ans = min(ans, sum); return ;}
for(int i = 1; i <= 5; i++)
if(!vis[i]) {vis[i] = 1; dfs(t + 1, sum + dis[per][a[i]], i); vis[i] = 0;}
}
/*----------------------------------------函数*/
int main()
{
// freopen("newyear8.in","r",stdin);
// freopen(".out","w",stdout);
n = read(); m = read();
for(int i = 1; i <= 5; i++) a[i] = read();
for(int i = 1; i <= m; i++)
{
int x = read(), y = read(), z = read();
add_edge(x, y, z);
}
a[6] = 1; emm(dis);
for(int i = 1; i <= 6; i++) dijk(i);
dfs(0, 0, 6);
printf("%d", ans);
// fclose(stdin);
// fclose(stdout);
return 0;
}
8. 最优贸易
/*
Time: 1.30
Worker: Blank_space
Source: #2590. 「NOIP2009」最优贸易
分层图 最短路
*/
/*--------------------------------------------*/
#include<cstdio>
#include<vector>
#include<queue>
#include<string.h>
#define emm(x) memset(x, 0x8f, sizeof x)
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
typedef pair <int, int> p;
struct edge {
int v, w;
};
std::vector <edge> e[C << 2];
int n, m, a[B], dis[B << 2];
queue <int> q;
bool vis[B << 2];
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
/*----------------------------------------函数*/
int main()
{
n = read(); m = read();
for(int i = 1; i <= n; i++) a[i] = read();
for(int i = 1; i <= m; i++)
{
int x = read(), y = read(), z = read();
e[x].push_back((edge){y, 0}); e[x].push_back((edge){n + y, -a[x]}); e[n + x].push_back((edge){2 * n + y, a[x]}); e[n + x].push_back((edge){n + y, 0}); e[2 * n + x].push_back((edge){2 * n + y, 0});
if(z > 1) {e[y].push_back((edge){x, 0}); e[y].push_back((edge){n + x, -a[y]}); e[n + y].push_back((edge){2 * n + x, a[y]}); e[n + y].push_back((edge){n + x, 0}); e[2 * n + y].push_back((edge){2 * n + x, 0});}
}
e[n].push_back((edge){3 * n + 1, 0}); e[3 * n].push_back((edge){3 * n + 1, 0});
q.push(1); emm(dis); dis[1] = 0;
while(!q.empty())
{
int u = q.front(); q.pop(); vis[u] = 0;
for(int i = 0; i < e[u].size(); i++)
{
int v = e[u][i].v, w = e[u][i].w;
if(dis[v] < dis[u] + w)
{
dis[v] = dis[u] + w;
if(!vis[v]) {q.push(v); vis[v] = 1;}
}
}
}
printf("%d", dis[3 * n + 1]);
return 0;
}
9. 汽车加油行驶问题
/*
Time: 1.30
Worker: Blank_space
Source: #6223. 「网络流 24 题」汽车加油行驶问题
说好的最短路呢...
尝试模拟建图 ... 然后没有然后了
题解:SPFA 暴力转移
*/
/*--------------------------------------------*/
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#define emm(x) memset(x, 0x3f, sizeof x)
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
int n, k, a, b, c, dis[110][110][11], mp[110][110], ans = INF;
int dx[5] = {0, 0, 0, 1, -1};
int dy[5] = {0, 1, -1, 0, 0};
struct node {
int x, y, z;
};
queue <node> q;
bool vis[110][110][11];
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
int min(int x, int y) {return x < y ? x : y;}
/*----------------------------------------函数*/
int main()
{
n = read(); k = read(); a = read(); b = read(); c = read();
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
mp[i][j] = read();
q.push((node){1, 1, k}); emm(dis); vis[1][1][k] = 1; dis[1][1][k] = 0;
while(!q.empty())
{
node h = q.front(); q.pop();
int x = h.x, y = h.y, z = h.z;
vis[x][y][z] = 0;
if(mp[x][y] && z != k)
{
if(dis[x][y][k] > dis[x][y][z] + a)
{
dis[x][y][k] = dis[x][y][z] + a;
if(!vis[x][y][k]) {vis[x][y][k] = 1; q.push((node){x, y, k});}
}
continue;
}
else
{
if(dis[x][y][k] > dis[x][y][z] + a + c)
{
dis[x][y][k] = dis[x][y][z] + a + c;
if(!vis[x][y][k]) {vis[x][y][k] = 1; q.push((node){x, y, k});}
}
}
if(z)
{
for(int i = 1; i <= 4; i++)
{
int xx = x + dx[i], yy = y + dy[i], t = 0;
if(xx < 1 || xx > n || yy < 1 || y > n) continue;
if(xx < x || yy < y) t = b;
if(dis[xx][yy][z - 1] > dis[x][y][z] + t)
{
dis[xx][yy][z - 1] = dis[x][y][z] + t;
if(!vis[xx][yy][z - 1]) {vis[xx][yy][z - 1] = 1; q.push((node){xx, yy, z - 1});}
}
}
}
}
for(int i = 0; i <= k; i++) ans = min(ans, dis[n][n][i]);
printf("%d", ans);
return 0;
}
10. 道路和航线
/*
Time: 1.30
Worker: Blank_space
Source: #10081. 「一本通 3.2 练习 7」道路和航线
先写个spfa试试 感觉会被卡
事实证明 裸的过不去
加点简单优化就好了
*/
/*--------------------------------------------*/
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#define emm(x) memset(x, 0x3f, sizeof x)
using namespace std;
/*--------------------------------------头文件*/
const int A = 1e4 + 7;
const int B = 1e5 + 7;
const int C = 1e6 + 7;
const int D = 1e7 + 7;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int FFF = 0x8fffffff;
/*------------------------------------常量定义*/
typedef pair <int, int> p;
struct edge {int v, w;};
vector <edge> e[B << 1];
int n, m1, m2, s, dis[A << 2];
bool vis[A << 2];
deque <int> q;
/*------------------------------------变量定义*/
inline int read() {
int x = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {x = (x << 3) + (x << 1) + (ch ^ 48); ch = getchar();}
return x * f;
}
/*----------------------------------------快读*/
/*----------------------------------------函数*/
int main()
{
n = read(); m1 = read(); m2 = read(); s = read();
for(int i = 1; i <= m1; i++)
{
int x = read(), y = read(), z = read();
e[x].push_back((edge){y, z}); e[y].push_back((edge){x, z});
}
for(int i = 1; i <= m2; i++)
{
int x = read(), y = read(), z = read();
e[x].push_back((edge){y, z});
}
emm(dis); dis[s] = 0; q.push_front(s);
while(!q.empty())
{
int u = q.front(); q.pop_front();
vis[u] = 0;
for(int i = 0; i < e[u].size(); i++)
{
int v = e[u][i].v, w = e[u][i].w, x = 0;
if(dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
if(!q.empty()) x = q.front();
if(!vis[v]) if(dis[v] > dis[x]) q.push_back(v); else q.push_front(v);
}
}
}
for(int i = 1; i <= n; i++)
if(dis[i] == INF) puts("NO PATH");
else printf("%d\n", dis[i]);
return 0;
}
——end