CJOJ 1217 【HAOI2005】路由选择问题
2017-04-12 19:28
357 查看
【HAOI2005】路由选择问题
任务一:在己知故障节点的情况下,求避开这些故障节点,从节点I到节点J的最短路径S0。
任务二:在不考虑故障节点的情况下,求从节点I到节点J的最短路径S1、第二最短路径S2。
第2—N+1行: Sk1 Sk2…SkN (节点K到节点J的距离为SkJ K=1,2,……,N)
最后一行: P T1 T2……Tp (故障节点的个数及编号)
0 10 5 0 0
10 0 0 6 20
5 0 0 30 35
0 6 30 0 6
0 20 35 6 0
1 2
(1)N<=50 N个节点的编号为1,2,…,N
(2)Skj为整数,Skj<=100,(K,J=1,2…,N 若Skj=0表示节点K到节点J没线路)
(3)P<=5
样例解释:
图论,最短路,次短路
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <map>
#include <vector>
#include <queue>
#define L 60
#define LL long long
using namespace std;
struct node {
int nxt, to, v;
} e[L << 1];
int n, st, se, P, p[L], minx = 2000000009, v, cnt, bj1 = 0, bj2 = 0, dis[L], head[L], pre[L];
bool vis[L], in[L];
queue <int> q;
inline void add(int a, int b, int c) {
e[++cnt].nxt = head[a], e[cnt].to = b, e[cnt].v = c, head[a] = cnt;
}
inline void spfa(int pd) {
while (!q.empty()) q.pop();
if (pd == 1) memset(pre, 0, sizeof(pre));
for (int i = 1; i <= n; ++i) in[i] = false, dis[i] = 2000000009;
dis[st] = 0, in[st] = true, pre[st] = -1, q.push(st);
while (!q.empty()) {
int x = q.front();
q.pop(), in[x] = 0;
for (int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if ((x == bj1 && y == bj2) || (x == bj2 && y == bj1)) continue;
if (vis[y]) continue;
if (dis[y] > dis[x] + e[i].v) {
dis[y] = dis[x] + e[i].v;
if (pd) pre[y] = x;
if (!in[y]) in[y] = 1, q.push(y);
}
}
}
}
int main(){
freopen("CJOJ1217.in", "r", stdin);
freopen("CJOJ1217.out", "w", stdout);
scanf("%d %d %d", &n, &st, &se);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) {
scanf("%d", &v);
if (v == 0) continue;
else add(i, j, v);
}
scanf("%d" ,&P);
for (int i = 1; i <= P; ++i) scanf("%d", &p[i]), vis[p[i]] = 1;
spfa(1), printf("%d ", dis[se]);
memset(vis, 0, sizeof(vis));
spfa(1), printf("%d ", dis[se]);
v = se;
while (pre[v] != -1) {
bj1 = v, bj2 = pre[v];
spfa(0);
minx = min(minx, dis[se]);
v = pre[v];
pre[st] = -1;
}
printf("%d", minx);
return 0;
}
Description
X城有一个含有N个节点的通信网络,在通信中,我们往往关心信息从一个节点I传输到节点J的最短路径。遗憾的是,由于种种原因,线路中总有一些节点会出故障,因此在传输中要避开故障节点。任务一:在己知故障节点的情况下,求避开这些故障节点,从节点I到节点J的最短路径S0。
任务二:在不考虑故障节点的情况下,求从节点I到节点J的最短路径S1、第二最短路径S2。
Input
第1行: N I J (节点个数 起始节点 目标节点)第2—N+1行: Sk1 Sk2…SkN (节点K到节点J的距离为SkJ K=1,2,……,N)
最后一行: P T1 T2……Tp (故障节点的个数及编号)
Output
S0 S1 S2 (S1<=S2 从节点I到节点J至少有两条不同路径)Sample Input
5 1 50 10 5 0 0
10 0 0 6 20
5 0 0 30 35
0 6 30 0 6
0 20 35 6 0
1 2
Sample Output
40 22 30Hint
【约束条件】(1)N<=50 N个节点的编号为1,2,…,N
(2)Skj为整数,Skj<=100,(K,J=1,2…,N 若Skj=0表示节点K到节点J没线路)
(3)P<=5
样例解释:
Source
[HAOI2005]图论,最短路,次短路
Solution
对于前面两个询问,直接spfa即可(同时记录最短路径),对于第三个询问,每一次删掉最短路径中的一条边,然后再spfa找到删过边后的最短边,即为次短边Code
#include <iostream>#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <map>
#include <vector>
#include <queue>
#define L 60
#define LL long long
using namespace std;
struct node {
int nxt, to, v;
} e[L << 1];
int n, st, se, P, p[L], minx = 2000000009, v, cnt, bj1 = 0, bj2 = 0, dis[L], head[L], pre[L];
bool vis[L], in[L];
queue <int> q;
inline void add(int a, int b, int c) {
e[++cnt].nxt = head[a], e[cnt].to = b, e[cnt].v = c, head[a] = cnt;
}
inline void spfa(int pd) {
while (!q.empty()) q.pop();
if (pd == 1) memset(pre, 0, sizeof(pre));
for (int i = 1; i <= n; ++i) in[i] = false, dis[i] = 2000000009;
dis[st] = 0, in[st] = true, pre[st] = -1, q.push(st);
while (!q.empty()) {
int x = q.front();
q.pop(), in[x] = 0;
for (int i = head[x]; i; i = e[i].nxt) {
int y = e[i].to;
if ((x == bj1 && y == bj2) || (x == bj2 && y == bj1)) continue;
if (vis[y]) continue;
if (dis[y] > dis[x] + e[i].v) {
dis[y] = dis[x] + e[i].v;
if (pd) pre[y] = x;
if (!in[y]) in[y] = 1, q.push(y);
}
}
}
}
int main(){
freopen("CJOJ1217.in", "r", stdin);
freopen("CJOJ1217.out", "w", stdout);
scanf("%d %d %d", &n, &st, &se);
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= n; ++j) {
scanf("%d", &v);
if (v == 0) continue;
else add(i, j, v);
}
scanf("%d" ,&P);
for (int i = 1; i <= P; ++i) scanf("%d", &p[i]), vis[p[i]] = 1;
spfa(1), printf("%d ", dis[se]);
memset(vis, 0, sizeof(vis));
spfa(1), printf("%d ", dis[se]);
v = se;
while (pre[v] != -1) {
bj1 = v, bj2 = pre[v];
spfa(0);
minx = min(minx, dis[se]);
v = pre[v];
pre[st] = -1;
}
printf("%d", minx);
return 0;
}
Summary
注意找次短边的方式相关文章推荐
- [HAOI2005]路由选择问题,次短路
- [HAOI2005]路由问题,第二短路
- [原创]带条件选择的并行汇聚路由问题
- VC2005中C运行时库选择不当导致的链接问题及解决方案
- VB 2005 - 读者询问 DrawString 问题—如何根据用户自己选择的颜色来绘制
- [原创]对“带条件选择的并行汇聚路由问题”的再思考
- VB 2005 - 读者询问 DrawString 问题—如何根据用户自己选择的颜色来绘制
- JBuilderX和JBuilder 2005的字体光标问题
- 关于回车自动跳转的问题,能不能有选择的跳转??
- 瑞星2005升级问题汇总
- 解决Web安装程序不能选择安装目录问题(2)
- XMLHTTP抓取数据时乱码问题解决 选择自 babyt 的 Blog
- 水晶报表中子报表的数据绑定问题 选择自 haozidong 的 Blog
- 解决Web安装程序不能选择安装目录问题(1)
- 瑞星2005升级问题汇总
- ES-IS:终端系统对中间系统路由选择交换协议--网络大典
- 解决Web安装程序不能选择安装目录问题(3)
- FlashCom中AvPresent组件自动选择的问题
- 关于WebWork2中的中文问题 选择自 chenyun2000 的 Blog (转载)
- 解决Web安装程序不能选择安装目录问题(4)