NYOJ115 城市平乱
2013-04-20 21:57
302 查看
题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=115
题目分析:这肯定是一条求最短路的题,最开始的想法是用floyd算法来做,结果悲剧的TLE。
反向广搜为什么就不对了呢?今天骑自行车的时候忽然想到,这样反向广搜是不对的,因为对每个节点如果有改进的话是会重复被压入队列的。所以有可能终点也在改进的过程中被反复的压入队列了,然后出队列的时候呢,可能就是同一个终点出来多次,导致有些终点的结果根本就没有遍历到。一个解决办法是把出队列的终点做上标记。如果后面同一个点出队列的时候,就不用++count了,那在进队列判断的时候也需要做相应的改正。
题目分析:这肯定是一条求最短路的题,最开始的想法是用floyd算法来做,结果悲剧的TLE。
int Map[1001][1001]; int dp[1001][1001]; int a[100]; int main() { int t,i,j,k; int n,m,p,q; int s, e, w; scanf("%d", &t); while(t--) { scanf("%d %d %d %d", &n, &m, &p, &q); for(i = 0; i < n; ++i) scanf("%d", &a[i]); for(i = 1; i <= m; ++i) for(j = 1; j <= m; ++j) Map[i][j] = 1e7; for(i = 0; i < p; ++i) { scanf("%d %d %d", &s, &e, &w); Map[s][e] = w; Map[e][s] = w; } memcpy(dp, Map, sizeof(Map)); for(k = 1; k <= m; ++k) for(i = 1; i <= m; ++i) for(j = 1; j <= m; ++j) dp[i][j] = dp[i][j] < dp[i][k] + dp[k][j] ? dp[i][j] : dp[i][k] + dp[k][j]; s = 1e7; for(i = 0; i < n; ++i) s = s < dp[a[i]][q] ? s : dp[a[i]][q]; printf("%d\n", s); } return 0; }没办法然后想着用广搜来做,居然过了,哎呀,伤心得很啊~
#include<stdio.h> #include<string.h> struct EDGE { int to; int w; }; EDGE edge[1001][1001];//edge[i][0].to存放的是节点i可达的节点数 int dp[1001]; int a[100]; int Queue[2001]; bool used[1001]; int BFS(int n, int q) { int head, tail,i; int temp,j; int ans = 1e7; for(i = 0; i < n; ++i)//对军队所在的每一个城市进行广搜 { memset(used, 0, sizeof(used)); Queue[0] = a[i]; used[a[i]] = true; dp[a[i]] = 0; head = 0; tail = 0; while(head <= tail) { temp = Queue[head]; if(temp == q)//遍历到终点,跳出循环 { ans = ans < dp[temp] ? ans : dp[temp]; break; } for(j = 1; j <= edge[temp][0].to; ++j) { //该节点没有用过,或者用过,但有更优的路径 if(!used[edge[temp][j].to] || dp[edge[temp][j].to] > dp[temp] + edge[temp][j].w) { used[edge[temp][j].to] = true; Queue[++tail] = edge[temp][j].to; dp[edge[temp][j].to] = dp[temp] + edge[temp][j].w; } }//end for j ++head; }//end for while }//end for i return ans; } int main() { int t,i; int n,m,p,q; int s, e, w; scanf("%d", &t); while(t--) { scanf("%d %d %d %d", &n, &m, &p, &q); for(i = 0; i < n; ++i) scanf("%d", &a[i]); for(i = 1; i <= m; ++i) edge[i][0].to = 0; for(i = 0; i < p; ++i) { scanf("%d %d %d", &s, &e, &w); ++edge[s][0].to; edge[s][edge[s][0].to].to = e; edge[s][edge[s][0].to].w = w; ++edge[e][0].to; edge[e][edge[e][0].to].to = s; edge[e][edge[e][0].to].w = w; } s = BFS(n, q); printf("%d\n", s); } return 0; }
反向广搜为什么就不对了呢?今天骑自行车的时候忽然想到,这样反向广搜是不对的,因为对每个节点如果有改进的话是会重复被压入队列的。所以有可能终点也在改进的过程中被反复的压入队列了,然后出队列的时候呢,可能就是同一个终点出来多次,导致有些终点的结果根本就没有遍历到。一个解决办法是把出队列的终点做上标记。如果后面同一个点出队列的时候,就不用++count了,那在进队列判断的时候也需要做相应的改正。
#include<stdio.h> #include<string.h> struct EDGE { int to; int w; }; EDGE edge[1001][1001]; int dp[1001]; int a[100]; int Queue[2001]; //终点标记为-1,其余点未访问标记为0,访问过标记为1; int used[1001]; int BFS(int n, int q) { int head, tail; int temp,j; int ans = 1e7; int count = 0; Queue[0] = q; used[q] = 1; dp[q] = 0; head = 0; tail = 0; while(head <= tail) { temp = Queue[head]; if(used[temp] == -1)//遍历到终点,跳出循环 { ans = ans < dp[temp] ? ans : dp[temp]; ++count;//问题主要是在这里,不是每次终点出队列的时候都要++count if(count == n) break; } for(j = 1; j <= edge[temp][0].to; ++j) { //该节点没有用过,或者用过,但有更优的路径 if(used[edge[temp][j].to] <= 0 || dp[edge[temp][j].to] > dp[temp] + edge[temp][j].w) { used[edge[temp][j].to] = !used[edge[temp][j].to] ? 1 : used[edge[temp][j].to]; Queue[++tail] = edge[temp][j].to; dp[edge[temp][j].to] = dp[temp] + edge[temp][j].w; } }//end for j ++head; }//end for while return ans; } int main() { int t,i; int n,m,p,q; int s, e, w; scanf("%d", &t); while(t--) { memset(used, 0, sizeof(used)); scanf("%d %d %d %d", &n, &m, &p, &q); for(i = 0; i < n; ++i) { scanf("%d", &a[i]); used[a[i]] = -1; } for(i = 1; i <= m; ++i) edge[i][0].to = 0; for(i = 0; i < p; ++i) { scanf("%d %d %d", &s, &e, &w); ++edge[s][0].to; edge[s][edge[s][0].to].to = e; edge[s][edge[s][0].to].w = w; ++edge[e][0].to; edge[e][edge[e][0].to].to = s; edge[e][edge[e][0].to].w = w; } s = BFS(n, q); printf("%d\n", s); } return 0; }
相关文章推荐
- NYOJ 115城市平乱 【dijkstra】
- nyoj115(城市平乱)(dijkstra算法)
- nyoj--115--城市平乱(最短路 反向)
- nyoj 115 城市平乱(spfa)
- nyoj 115 城市平乱 dijkstra最短路
- NYOJ-115 城市平乱
- NYOJ-115 城市平乱
- nyoj 115 城市平乱 dijkstra最短路
- nyoj 115城市平乱
- nyoj 115 城市平乱
- nyoj 115 城市平乱
- NYOj115-城市平乱-Dijkstra-
- 城市平乱(nyoj 115)单源最短路径
- HDUOJ1874 畅通工程续 和 NYOJ 115 城市平乱【Dijkstra 算法】
- nyoj 115 城市平乱 迪杰斯特拉
- nyoj 115 城市平乱
- nyoj 115 城市平乱(dijkstra 终点当起点)
- NYOJ 115 城市平乱
- NYOJ 115 城市平乱【Dijkstra】
- Dijkstra算法 NYOJ115城市平乱