【最短路】解题报告
2011-11-01 09:42
253 查看
4.最短路(path.c/cpp)
[问题描述]
给定一个包含N个点,M条边的无向图,每条边的边权均为1。
再给定K个三元组(A,B,C),表示从A点走到B点后不能往C点走。注意三元组是有序的,如可以从B点走到A点再走到C。
现在你要在K个三元组的限制下,找出1号点到N号点的最短路径,并输出任意一条合法路径,会有Check检查你的输出。
[输入格式]
输入文件第一行有三个数N,M,K,意义如题目所述。
接下来M行每行两个数A,B,表示A,B间有一条边。
再下面K行,每行三个数(A,B,C)描述一个三元组。
[输出格式]
输出文件共两行数,第一行一个数S表示最短路径长度。
第二行S+1个数,表示从1到N所经过的节点。
[样例输入]
4 4 2
1 2
2 3
3 4
1 3
1 2 3
1 3 4
[样例输出]
4
1 3 2 3 4
[数据范围]
对于40%的数据满足N≤10,M≤20,K≤5。
对于100%的数据满足N≤3000,M≤20000,K≤100000。
这道题是一道拆点的题,不过也可以用广搜来做,每次记录父亲就行了。
一开始我就卡在了这点上,走到下一个点,但是并不知道这个状态是由哪一个父亲派生出来的,但是其实就是这么简单,对每个队列中的元素都记录父亲。
广搜:
spfa+拆点
意思容易理解,只是代码不好写,因为结构体太多了。容易混淆
拆点关键就在于,对于hash、dist、还有记录方案的g统统都要增加一维。
上个方案的bfs中,hash增加了一维也是基于这个原因,因为不能从上一个点到这个点来了,但是还会有其他的路到这个点来
[问题描述]
给定一个包含N个点,M条边的无向图,每条边的边权均为1。
再给定K个三元组(A,B,C),表示从A点走到B点后不能往C点走。注意三元组是有序的,如可以从B点走到A点再走到C。
现在你要在K个三元组的限制下,找出1号点到N号点的最短路径,并输出任意一条合法路径,会有Check检查你的输出。
[输入格式]
输入文件第一行有三个数N,M,K,意义如题目所述。
接下来M行每行两个数A,B,表示A,B间有一条边。
再下面K行,每行三个数(A,B,C)描述一个三元组。
[输出格式]
输出文件共两行数,第一行一个数S表示最短路径长度。
第二行S+1个数,表示从1到N所经过的节点。
[样例输入]
4 4 2
1 2
2 3
3 4
1 3
1 2 3
1 3 4
[样例输出]
4
1 3 2 3 4
[数据范围]
对于40%的数据满足N≤10,M≤20,K≤5。
对于100%的数据满足N≤3000,M≤20000,K≤100000。
这道题是一道拆点的题,不过也可以用广搜来做,每次记录父亲就行了。
一开始我就卡在了这点上,走到下一个点,但是并不知道这个状态是由哪一个父亲派生出来的,但是其实就是这么简单,对每个队列中的元素都记录父亲。
广搜:
#include <cstdio> struct node { long y; long z; node* next; }; node* g[3002][3002]; long n;long m;long k; long que[1100000]; long que2[1100000]; long fa[3002]; bool map[3002][3002]; void insert(long x,long z,long y) { node* tmp = new node; tmp -> z = z; tmp -> y = y; tmp -> next = g[x][y]; g[x][y] = tmp; } void output(long p) { if (fa[p]==0) { printf("%ld ",que[p]); return; } output(fa[p]); printf("%ld ",que[p]); } bool check(long a,long b) { node* ths = g[fa[a]][b]; while (ths) { if (ths->z==a) return false; ths = ths->next; } return true; } void bfs() { long l= 0;long r= 0; r++; que[r] = 1; while (l<r) { long now = que[++l]; for (long i=1;i<n+1;i++) { if (now == i)continue; if (map[now][i]&&check(l,i)) { map[now][i] = false; r++; fa[r] = l; que[r] = i; que2[r] = que2[l]+1; if (i==n) { printf("%ld\n",que2[r]); output(r); return; } } } } } int main() { freopen("path.in","r",stdin); freopen("path.out","w",stdout); scanf("%ld%ld%ld",&n,&m,&k); for (long i=1;i<m+1;i++) { long a;long b; scanf("%ld%ld",&a,&b); map[a][b] = true; map[b][a] = true; } for (long i=1;i<k+1;i++) { long a;long b;long c; scanf("%ld%ld%ld",&a,&b,&c); insert(a,b,c); } bfs(); return 0; }
spfa+拆点
意思容易理解,只是代码不好写,因为结构体太多了。容易混淆
拆点关键就在于,对于hash、dist、还有记录方案的g统统都要增加一维。
上个方案的bfs中,hash增加了一维也是基于这个原因,因为不能从上一个点到这个点来了,但是还会有其他的路到这个点来
#include <cstdio> struct node { long z; node* next; }; node* g[3002][3002]; struct node1 { long index; node1* next; }; struct tnode { long f; long i; }; long n;long m;long k; tnode que[100000]; bool map[3002][3002]; node1* dian[3002]; bool used[3002][3002]; long dist[3002][3002]; long fangan[3002][3002]; void insert1(long x,long y) { node1* tmp = new node1; tmp->index = y; tmp->next = dian[x]; dian[x] = tmp; } void insert(long x,long y,long z) { node* tmp = new node; tmp -> z = z; tmp -> next = g[x][y]; g[x][y] = tmp; } bool can(long a,long b,long c) { node* ths = g[a][b]; while (ths) { if (ths->z==c) return false; ths = ths->next; } return true; } void spfa() { for (long i=0;i<n+1;i++) { for (long j=0;j<n+1;j++) { dist[i][j] = 0x7fff0000; } } used[1][1] = true; dist[1][1] = 0; long l = 0; long r = 1; que[r].f=1; que[r].i=1; while (l<r) { l++; tnode now = que[l]; used[now.f][now.i] = false; node1* ths = dian[now.i]; while (ths) { if (can(now.f,now.i,ths->index)&&dist[now.i][ths->index]>dist[now.f][now.i]+1) { dist[now.i][ths->index]=dist[now.f][now.i]+1; fangan[now.i][ths->index] = l; if (!used[now.i][ths->index]) { used[now.i][ths->index] = true; r++; que[r].i = ths->index; que[r].f = now.i; } } ths = ths -> next; } } } void output(long a,long b) { if(b==1) { printf("1 "); return; } tnode* la = &que[fangan[a][b]]; output(la->f,la->i); printf("%ld ",b); } int main() { freopen("path.in","r",stdin); freopen("path.out","w",stdout); scanf("%ld%ld%ld",&n,&m,&k); for (long i=1;i<m+1;i++) { long a;long b; scanf("%ld%ld",&a,&b); insert1(a,b); insert1(b,a); } for (long i=1;i<k+1;i++) { long a;long b;long c; scanf("%ld%ld%ld",&a,&b,&c); insert(a,b,c); } spfa(); long ans = 0x7fff0000; long t = 0; for (long i=1;i<n;i++) { if (dist[i] <ans) { ans=dist[i] ; t=i; } } printf("%ld\n",ans); output(t,n); return 0; }
相关文章推荐
- codevs 1062 路由选择 最短路次短路 dijkstra 解题报告
- poj 1062 昂贵的婚礼 最短路 dijkstra 解题报告
- BZOJ 4152 最短路(SPFA) 解题报告
- csu 1307 City Tour dijkstra+并查集 最短路 解题报告
- POJ - 3268 Silver Cow Party解题报告(dijkstra分别求单源起点和单源终点的最短路)
- hdu2544 最短路(floyd) 解题报告
- hdu 1142 A Walk Through the Forest 最短路+记忆化搜索 解题报告
- luogu解题报告:P1119灾后重建【图论/最短路】
- poj 2449 Remmarguts' Date 第k短路 A*+spfa 解题报告
- HDU6166 Senior Pan 解题报告【图论】【SPFA最短路】【随机】
- 【解题报告】POJ 2449 Remmarguts' Date -- 有向图第k短路(有重边)
- CDOJ 30 最短路 解题报告
- 团体程序设计天梯赛-练习集 L3-011. 直捣黄龙 最短路 dijkstra 解题报告
- AcDream 1415 Important Roads 解题报告(最短路 + 线段树)
- hdu2544 最短路(Dijkstra) 解题报告
- luogu解题报告:P1186玛丽卡【图论/最短路/堆优化dijkstra】
- hdu 2544 最短路 Bellman_Ford 解题报告
- pku2243马棋到达最短路解题报告
- HDU 3339 In Action 解题报告(最短路+背包)
- HDU2544 最短路 解题报告--Dijkstra