Stockbroker Grapevine(AC) Bellman Ford算法
这道题我用的是Bellman Ford算法,用其他的最短路径算法(Floyd、Dijstra)也可。
#include <iostream> #include <memory.h> using namespace std; int weight[101][101]; int dis[101]; int pi[101]; int minTime = 10000; //最多有 100 * (100-1) 条边,每个边有两个节点 int edgeStack[100 * (100-1) * 2]; //Index 首字母大写,因为 index 在函数库中另有含义 int Index = 0; int vertexNum = 0;int edgeNum = 0; void PushEdge( int i, int j) { //注意前后置的 ++ 运算符与 Index 的上限的大小关系,要相应 -2 和 -1 if (Index <= 100*(100-1)*2-1-1) { edgeStack[Index++] = j; edgeStack[Index++] = i; } } void PopEdge( int &i, int &j) { if (Index >= 2) { i = edgeStack[--Index]; j = edgeStack[--Index]; } } void input() { int p; int cost; for ( int j=1; j<=vertexNum; j++) { int edge; cin >> edge; edgeNum += edge; for ( int i=1; i<=edge; i++) { cin >> p >> cost; weight[j][p] = cost; PushEdge(j, p); } } } const int MAX = 10000; const int NIL = -1; void Initialize_Single_Source( int s) { for ( int i=1; i<=101; i++) { dis[i] = MAX; pi[i] = NIL; } dis[s] = 0; } void Relax( int u, int v) { if (dis[v] > dis[u] + weight[u][v]) { dis[v] = dis[u] + weight[u][v]; pi[v] = u; } } bool Bellman_Ford( int s) { Index = edgeNum * 2; //在每一次调用 Bellman_Ford 时,要记得将 edgeStack 数组下标归末; int u, v; Initialize_Single_Source(s); for ( int i=0; i<vertexNum-1; i++) { for ( int j=0; j<edgeNum; j++) { PopEdge(u, v); Relax(u, v); } Index = edgeNum * 2; //这里也是 } for ( int i=0; i<edgeNum; i++) //这个循环对这道题来说不是必要的,但为了理解算法导论的算法,就把负环路检测的代码加上了 { PopEdge(u, v); if (dis[v] > dis[u] + weight[u][v]) { return false ; } } return true ; } int SelectMax( int dist[101]) { int max = 0; for ( int i=1; i<=vertexNum; i++) //注意这里是 vertexNum 不是 edgeNum,因为 dis 数组保存的是原点 s 至每个点的当前最短距离 { //因为这个问题,程序一度中止; if (dist[i] > max) { max = dist[i]; } } return max; } int main() { int ss; cin >> vertexNum; while (vertexNum != 0) { edgeNum = 0; Index = 0; memset (weight, 0, sizeof (weight)); memset (edgeStack, 0, sizeof (edgeStack)); minTime = 10000; input(); for ( int s=1; s<=vertexNum; s++) { Bellman_Ford(s); int maxTime = SelectMax(dis); if (maxTime < minTime) { minTime = maxTime; ss = s; } } if (minTime != MAX) { cout << ss << ' ' ; Bellman_Ford(ss); cout << minTime << endl; } else //不要忘了检测 disjoint(非连通); { cout << "disjoint" << endl; } cin >> vertexNum; } return 0; } |
我用数组保存输入的边,以供 Bellman-Ford 算法使用。也可以在 Bellman-Ford 算法中检查 weight 数组的值是否修改,以确定一对节点是否连通,不过这样的话要多一重循环。考虑到时间复杂度,我选择前一种方法。不过,代码多了一倍,也用了更多的时间。总之,各有利弊。在 PushEdge 和 PopEdge 两个函数上的前后置运算符Index++, --index上用了一些时间,一定要记得,如果 PushEdge 中使用 Index++,PopEdge 就一定要用 --index。(久不写代码,生疏了。)
分类:
图论(Graph Theory)
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】博客园携手 AI 驱动开发工具商 Chat2DB 推出联合终身会员
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个超经典 WinForm,WPF 卡死问题的终极反思
· ASP.NET Core - 日志记录系统(二)
· .NET 依赖注入中的 Captive Dependency
· .NET Core 对象分配(Alloc)底层原理浅谈
· 聊一聊 C#异步 任务延续的三种底层玩法
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(一):从.NET IoT入
· .NET 开发的分流抢票软件,不做广告、不收集隐私
· 一个超经典 WinForm,WPF 卡死问题的终极反思
· 实现windows下简单的自动化窗口管理
· 前端实现 HTML 网页转 PDF 并导出