HDU 2433 Travel
来源:互联网 发布:淘宝联盟怎么得佣金 编辑:程序博客网 时间:2024/06/06 00:26
Travel
Time Limit : 10000/2000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Total Submission(s) : 11 Accepted Submission(s) : 4
Let SUM be the total distance of the shortest paths between all pairs of the towns. Please write a program to calculate the new SUM after one of the M roads is destroyed.
5 45 11 33 25 42 21 21 2
INFINFINFINF22
题目意思:
第一行输入两个数字N,M,N是城市个数,M是道路条数,路的长度恒为1,然后接下来给出M条边,这个边是无方向的,即可以通过这条路从城市1
到城市2,也可以从城市2到城市1,依次输出删除第i条边后,图中任意两点最短路径的和值,如果删除第i条边后,有两个城市间不存在最短路径了,就输出INF。
解题思路:
这个题,好心累,看了一下午题解。
1.英文的,题目意思难理解。 2.理解了之后也发现不会写。本来只会Dijstra和Flody两种最短路算法,因为题目中要的是任意两点的最短路径和,则刚开始会想到Flody,但是其本身时间复杂度高,而且这个题目删除一条边后,都要Flody,题目给最多给100个顶点,Flody一次最多100*100*100.题目又最多给出3000条边,删除一条边一次Flody一次,最多3000*100*100*100的时间复杂度,不可能了。因为题目说了任何一边其距离都为1,则可以用广搜。存储图用容器,其实和临界链表存储是一样的。基本思路是还是要先求出每个点到其他点的最短路径和,然后再考虑删除边的影响。
注意下面几点:
1.初始求每个点到其他点的最短路,如果发现某个点到另一个点是没有最短路径的时候,则图自身就不能保证任意两点之间存在最短路径,此时不用再
去考虑删除M条边了。直接输出M个INF就可以了。
2.如果图任意两点间都能求出最短路径,考虑删除第i条边,如果有重复的边,则删除该边后,对答案没有影响,直接输出答案就可以了。
3.如果删除该边i后,某两个顶点间没有直接通路。那么考虑N个顶点,如果顶点t到其他点的最短路用到了这两个顶点,重新求t到其他最短路的值。
这时如果发现t与某一顶点没有最短路径了,则直接输出INF,不用再考虑后面的点了。
看了一下午别人的题解,终于理清思路了,遇到不会的知识尽力去学习就有收获,开心。
#include<iostream>#include<cstdio>#include<queue>#include<vector>#include<cstring>#define INF 0x3f3f3f3f#define MAXN 103using namespace std;int N,M; ///N个顶点,M条边struct edge{ int s; ///起点 int d; ///终点};struct edge E[3002]; ///用来存放边的数组vector<int>node[MAXN]; ///用容器来存放图,相当于临接链表int used[MAXN][MAXN][MAXN]; ///used[x][u][v],以x为源点的广搜树用到了u-v这条边int road[MAXN][MAXN]; ///该数组用来记录u-v路的条数,要知道如果有重边,删除后是没有影响的。int sum[MAXN]; ///sum[i]用来存放以i为源点到其他点最短路径的和int dis[MAXN]; ///用来存放以某个点为源点到其它点的最短路径int vis[MAXN]; ///用来记录标记的数组。int ans; ///用于存放答案void GetEdge() ///获取边信息初始化图的函数{ int i,j,u,v; for(i = 1; i <= N; i++) { node[i].clear(); ///清空节点i所对应的容器 for(j = 1; j <= N;j++) { road[i][j] = 0; ///任意两个顶点之间的路的条数都初始化为0 } } for(i = 0; i < M; i++) ///输入M条边 { scanf("%d%d",&u,&v); ///顶点u到顶点v有一条边 E[i].s = u; E[i].d = v; ///注意图是无向图 node[u].push_back(v); ///顶点u的后继顶点之一是v node[v].push_back(u); ///顶点v的后继顶点之一是u road[u][v]++; ///u到v的道路条数和v到u的道路条数都增加1 road[v][u]++; }}int spfa_bfs1(int start) ///该函数求未删除任何边时,某个源点到其他点的最短路{ int i,j,cur,nex; for(i = 1; i <= N; i++) ///初始化起点start到其他点的最短路径 { dis[i] = INF; vis[i] = 0; } dis[start] = 0; ///标记起点并入队 vis[start] = 1; queue<int>qu; qu.push(start); while(!qu.empty()) { cur = qu.front(); qu.pop(); vis[cur] = 0; for(int i = 0; i < node[cur].size(); i++) { nex = node[cur][i]; if(dis[cur]+1 < dis[nex]) ///如果start到cur再到nex比start到nex的最短路小 { dis[nex] = dis[cur]+1; used[start][cur][nex] = used[start][nex][cur] = 1; ///标记 if(vis[nex] == 0) { vis[nex] = 1; qu.push(nex); } } } } int temp = 0; for(i = 1; i <= N; i++) { if(dis[i]<INF) temp = temp + dis[i]; else ///代表图本身就有两个点不通 return -1; } return temp;}int spfa_bfs2(int start) ///删除某条边后,重新求最短路{ int i,j,cur,nex; for(i = 1; i <= N; i++) { dis[i] = INF; vis[i] = 0; } dis[start] = 0; vis[start] = 1; queue<int>qu; qu.push(start); while(!qu.empty()) { cur = qu.front(); qu.pop(); vis[cur] = 0; for(i = 0; i < node[cur].size(); i++) { int nex = node[cur][i]; if(road[cur][nex]) ///因为删除了某条路,需要判断是否有路 { if(dis[cur]+1 < dis[nex]) { dis[nex] = dis[cur]+1; if(vis[nex]==0) { vis[nex] = 1; qu.push(nex); } } } } } int temp = 0; for(i = 1; i <= N; i++) { if(dis[i]<INF) temp += dis[i]; else ///说明start到i的最短路为INF,代表没有路径。 return -1; } return temp;}int main(){ int i,j,flag,status,t; while(~scanf("%d%d",&N,&M)) { memset(used,0,sizeof(used)); ///初始化used数字 flag = 1; ///flag用来标记题目给的图是否任意两点间都连通,初始时1,代表任意两点间都连通 ans = 0; GetEdge(); ///获取边 for(i = 1; i <= N; i++) { sum[i] = spfa_bfs1(i); if(sum[i] == -1) ///代表i到某点无最短路,flag状态改变 { flag = 0; break; } ans += sum[i]; ///加上第i个点到其他点的最短路径和 } if(flag) ///题目数据本身构成的图任意两点之间都有最短路 { for(i = 0; i < M; i++) ///用来删除第M条边 { int a = E[i].s; int b = E[i].d; ///删除第i条边 road[a][b]--; road[b][a]--; if(road[a][b]>0) ///顶点a与顶点b之间有重边,删除一条边无影响 { printf("%d\n",ans); } else ///如果删除一条边a,b之间没有边了 { int temp = ans; status = 1; for(j = 1; j <= N; j++) { if(used[j][a][b]) ///如果以j为源点用到了边a,b重新求其到其他边的最短路 { temp = temp - sum[j]; t = spfa_bfs2(j); ///求删除a,b后,j到其他点新的最短路径和 if(t == -1) ///删除一条边a,b后,j到某个点不通了 { printf("INF\n"); ///直接输出INF status = 0; break; } temp = temp + t; } } if(status) printf("%d\n",temp); } road[a][b]++; ///注意恢复图原来的状态 road[b][a]++; } } else ///题目所给数据本身不能满足任意两点间存在最短路径,直接输出M个INF { for(i = 1; i <= M; i++) printf("INF\n"); } } return 0;}
- hdu 2433 TRAVEL
- HDU 2433 - Travel
- HDU 2433 Travel
- HDU 2433 Travel
- hdu 2433 Travel 最短路
- hdu 2433 Travel bfs+剪枝
- hdu 2433 Travel(spfa)
- hdu Travel
- hdu-travel
- Travel HDU
- Travel HDU
- Travel HDU
- hdu 2433 Travel 最短路+预处理
- Hdu 2433 Travel 删边+最短路之和
- 【HDU】2433 Travel 最短路树优化
- HDU 2433 Travel 最短路SPAF
- hdu 2433 Travel 最短路 dijkstra算法。
- HDU 2433 Travel 最短路树
- 9.Selenium2 自动化测试实战-基于Python语言-键盘事件
- 剑指offer-树的子结构
- RTP Payload H264
- C#中引用传递与指针传递区别
- 关于资源文件R
- HDU 2433 Travel
- java进入Catalina步骤查看引擎VxBPEL部署的工程以及对VxBPEL工程进行配置
- 基于单链表的生产者消费者问题
- Java NIO系列教程(五) 通道之间的数据传输
- C# 24位彩图转8位灰度图
- 字符串函数
- Action_九宫格
- qtquick 学习之二
- 基于base64位编码上传图片POST提交值得注意的地方