[转]HDU 2433 Travel 最短路 预处理优化
2017-04-15 21:38
330 查看
原文地址:http://http://blog.csdn.net/linraise/article/details/42155947
题意是说算出一个图所有点到其他点的最短路的和,然后进行删除某条边再进行处理,对SPFA本来也不是很熟,改来改去始终没能A掉,所以转载一篇,参考代码= =
思路:
个人认为这道题的描述有问题,但是不在意这些细节了。题目的大致意思是:给定一个图,邻接顶点距离恒为1,
对每一个点都算出其它任意的点到它的最小距离总和。再把所有点的总和相加得到的就是结果。顶点数为N,因为
邻接点距离恒为1,可以用BFS生成一棵以当前顶点为根的最小树。所有节点到根的距离总和就是一个顶点的距离。
如果使用蛮力法,生成一棵最小树BFS时间复杂度为O(n),n<100,共有n个结点O(n*n),每删一条边(m)就需要重新生成,
总复杂度为O(n*n*m)。显然是不可接受的。题目的用意也清晰,就是要我们空间换时间,优化之。没有必要每删一条边就
重新生成一棵BFS最小树。如果删的边不是BFS最小树的树边,忽略之。直接记录最小树的距离结果。
优化点一容易得出:每生成一棵BFS树,就把它的距离记录下来。如果删边不在树上,则直接取之。
如果图本身就不是连通图,则可以输出m个INF就完事,优化点二得到。
优化点三也容易想到:如果删除的边是重边,则也是无影响的。
最坏的情况:删的边刚好是树边,则老实地重新BFS生成最小树。(但是需要十分注意不能破坏图结构和污染已记录的BFS树距离)
题意是说算出一个图所有点到其他点的最短路的和,然后进行删除某条边再进行处理,对SPFA本来也不是很熟,改来改去始终没能A掉,所以转载一篇,参考代码= =
思路:
个人认为这道题的描述有问题,但是不在意这些细节了。题目的大致意思是:给定一个图,邻接顶点距离恒为1,
对每一个点都算出其它任意的点到它的最小距离总和。再把所有点的总和相加得到的就是结果。顶点数为N,因为
邻接点距离恒为1,可以用BFS生成一棵以当前顶点为根的最小树。所有节点到根的距离总和就是一个顶点的距离。
如果使用蛮力法,生成一棵最小树BFS时间复杂度为O(n),n<100,共有n个结点O(n*n),每删一条边(m)就需要重新生成,
总复杂度为O(n*n*m)。显然是不可接受的。题目的用意也清晰,就是要我们空间换时间,优化之。没有必要每删一条边就
重新生成一棵BFS最小树。如果删的边不是BFS最小树的树边,忽略之。直接记录最小树的距离结果。
优化点一容易得出:每生成一棵BFS树,就把它的距离记录下来。如果删边不在树上,则直接取之。
如果图本身就不是连通图,则可以输出m个INF就完事,优化点二得到。
优化点三也容易想到:如果删除的边是重边,则也是无影响的。
最坏的情况:删的边刚好是树边,则老实地重新BFS生成最小树。(但是需要十分注意不能破坏图结构和污染已记录的BFS树距离)
//2433 bround first search //题意真是不清楚,早说是所有点距离全加起来啊 #include <iostream> #include <queue> #include <algorithm> using namespace std; typedef struct Edge { int beg,end; } Edge; Edge edge[3001]; int Sum[101] = {0}; int Map[101][101]; bool visited[101]; int prec[101][101]; // prefix,prec[i] store the i-th bfs tree int N,M; int BFS(int k,bool is_preprocess = true) { int dis[101] = {0}; memset(visited,false,sizeof(visited)); queue<int> Q; visited[k] = true; Q.push(k); int cnt = 1; int Sum = 0; while (!Q.empty()) { int i = Q.front();Q.pop(); for (int j=1; j <= N; ++j) { if (!visited[j] && Map[i][j] > 0) { visited[j] = true; if (is_preprocess) prec[k][j] = i; //记录前驱,只记录第一次遍历的BFS树的节点前驱 dis[j] = dis[i] + 1; Sum += dis[j]; ++cnt; Q.push(j); } } } return (cnt==N) ? Sum : -1; } int main() { #ifndef ONLINE_JUDGE freopen("1.txt","r",stdin); #endif int x,y, sum ; while (cin >> N >> M) { memset(Sum,0,sizeof(Sum)); memset(Map,0,sizeof(Map)); memset(prec,0,sizeof(prec)); int i=1; for ( ;i <= M; ++i) { //build the graph cin >> x >> y; Map[x][y]++; Map[y][x]++; edge[i].beg = x; edge[i].end = y; } sum = 0; i=1; for (; i <= N; ++i) { Sum[i] = BFS(i); if (Sum[i]==-1) break; else sum += Sum[i]; } if (i <= N) //原图为非连通图,无论删哪条边,距离恒为INF { for (int i=0; i < M; ++i) puts("INF"); continue; } for (int i=1; i <= M; ++i) { int x = edge[i].beg; int y = edge[i].end; if (Map[x][y] > 1) //有重边,删除其中一条对全图无影响 { cout << sum << endl; } else //删的是割边(不可能有Map[][]==0,因为前边过滤了非连通图) { int sum1 = 0,j=1,s1; for (; j <= N; ++j)//遍历全部顶点,蛮力法 { if (prec[j][y]==x || prec[j][x]==y)//x-y在第j棵bfs树上,只能蛮力 { Map[x][y] = Map[y][x] = 0; //删边 s1 = BFS(j,false); if (s1==-1) //非连通,直接返回INF { Map[x][y] = Map[y][x] = 1; //恢复边 break; } sum1 += s1; Map[x][y] = Map[y][x] = 1; //恢复边 } else { sum1 += Sum[j]; } } if (j <= N) { puts("INF"); // continue; } else { cout << sum1 << endl; } } } } return 0; }
相关文章推荐
- hdu 2433 Travel 最短路+预处理
- 【HDU】2433 Travel 最短路树优化
- hdu 2433 Travel (bfs+最短路生成树+剪枝)
- hdu 2433 Travel 最短路
- HDU - 2433 Travel (最短路树)
- HDU 2433 Travel (最短路,BFS,变形)
- 【最短路+bfs+剪枝】杭电 hdu 2433 Travel
- HDU 2433 Travel 最短路SPAF
- 【hdu】2433 Travel【最短路删边】
- HDU 2433 Travel 最短路树
- HDU 2433 Travel 最短路应用
- HDU 2433 Travel 枚举+最短路
- HDU 2433 Travel 最短路树
- HDU-2433 Travel(最短路[Dijkstra])
- hdu 2433 Travel(枚举删掉的边求取最短路)
- hdu 2544 【总结】 Dijkstra,Bellman-Ford ,SPFA 最短路求法及对应优化
- hdu 2066最短路 dijkstra 及其优先队列优化
- HDU 1535 Invitation Cards (最短路,附SLF优化SPFA)
- HDU 2544 最短路——贝尔曼福特(结构体&优化) spfa算法
- [HDU 2544] 最短路 · 堆优化dijkstra