// // // // // // // // // // // // // //

关于最短路

最短路

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

posted @ 2021-01-30 14:21  Blank_space  阅读(57)  评论(0编辑  收藏  举报
// // // // // // //