✨欢迎来到脑子不好的小菜鸟的文章✨
🎈创作不易,麻烦点点赞哦🎈
我的主页:脑子不好的小菜鸟
文章特点:关键点和步骤讲解放在
代码相应位置
-
- //拓扑排序:找到入度为0的点,将其写入答案,再删去其箭头,再继续找入度为0的点,循环往复
-
- vector<int>edeg[101];
- int n, deg[101] = { 0 };//入度
- void init()//建图
- {
- cin >> n;
- int i, val;
- for (i = 1; i <= n; i++)
- {
- while (cin >> val && val != 0)
- {
- edeg[i].push_back(val);
- deg[val]++;
- }
- }
- }
-
- void toposort()//拓扑排序
- {
- int i;
- queue<int> que;
- for (i = 1; i <= n; i++)
- {
- if (deg[i] == 0)
- {
- cout << i << ' ';
- que.push(i);
- }
- }
-
- while (!que.empty())
- {
- int t = que.front();
- que.pop();
-
- for (int i : edeg[t])
- //相当于i表示edeg[t]的第一个元素,进行一次循环后就是第二个元素,循环往复
- {
- deg[i]--;
- if (deg[i] == 0)
- {
- cout << i << ' ';
- que.push(i);
- //push的原因:可能i(也就是edeg[t])还有箭头指向其他的数,也就是后面辈分比它小的,要通过i来找比它辈分小的
- }
- }
- }
- }
-
- int main()
- {
- init();//建图
- toposort();//拓扑排序
- return 0;
- }
- ///*法一:邻接矩阵*/
- 占的空间较多,时间复杂度较大,不适合
-
-
- /*法二:结构体,堆优化*/
- //要一个结构体,存一个点相关的东西(to, wei, next)(终点, 权值, 下一个儿子)
- //cnt:结构体下标
- //head[MAX]:head[i]:查找i点的第一个儿子
- //pos:将被标记的值
- //ans[MAX]:最短距离
- //visit[MAX]:是否被标记过
-
- //题解:https://www.luogu.com.cn/article/oswxjzrl
- #include
#include - using namespace std;
- const int MAX = 1e6;int cnt;//结构体下标int visit[MAX];//标记int n, m, s;int head[MAX];//存放儿子int ans[MAX];//放到起点的最短距离
- struct EDGE
- {
- int wei;//权值
- int to;//目的地
- int next;//下一个儿子
- }edge[MAX];
- void add(int u, int v, int w){
- cnt++;
- edge[cnt].wei = w;
- edge[cnt].to = v;
- edge[cnt].next = head[u];//将下一个儿子记录
- head[u] = cnt;//更新第一个儿子
- }
- int main(){
- cin >> n >> m >> s;
- int i;
-
- //初始化ans
- for (i = 1; i <= n; i++)
- ans[i] = INT_MAX;
-
- ans[s] = 0;
-
- int u, v, w;
- for (i = 1; i <= m; i++)
- {
- cin >> u >> v >> w;
- add(u, v, w);
- }
-
- int pos = s;//初始化pos为s
- while (visit[pos] == 0)
- {
- int minn = INT_MAX;//注意更新
- visit[pos] = 1;//标记
-
- //更新儿子的最短路径
- for (i = head[pos]; i != 0; i = edge[i].next)
- {
- if (visit[edge[i].to] == 0 && ans[edge[i].to] > ans[pos] + edge[i].wei)
- ans[edge[i].to] = ans[pos] + edge[i].wei;
- }
-
- //找最短路径
- for (i = 1; i <= n; i++)
- {
- if (visit[i] == 0 && ans[i] < minn)
- {
- minn = ans[i];
- pos = i;
- }
- }
- }
-
- for (i = 1; i <= n; i++)
- cout << ans[i] << ' ';
- cout << endl;
- return 0;
- }
注意:该题用上一题的代码会超时,因此要用堆优化,也就是优先队列
-
-
- //友情提示:正权图 请 使用dijkstra算法, 负权图 请 使用SPFA算法
-
- //弱化版的代码超时---->要用堆优化
- /*
- 核心:priority_queue< pair
> 用优先队列来取最近的点,就不用遍历找点了 - 在pq中,是按pair的第一个元素(first)由大到小排序的,所以pair<距离,点号>,注意因为要的是最小值,所以距离要存负值
- 其实距离是纯纯的工具人,我们只是需要它来维持点的排序
- 每次取队首h,取出的就是dis最短的点
- 还要注意:
- 如果这个点的dis不等于h的dis,说明这个点在入队之后被更新了,那么我们就不用这个点了,直接continue;
- 因为后面会有个h2点比h1的dis更小,用h1更新就没有意义了
- */
-
- //使用优先队列,注意:优先队列是从大到小排列,所以存进去应该存负数
-
- C代码:
- #include
- /*堆优化:利用优先队列,降低复杂度,直接排序,注意优先队列是由大到小排列的,因此距离是负数 */
- #include
- #include
-
- using namespace std;
-
- const int MAX = 1e6;
- int n, m, s;
- int ans[MAX];
- int cnt;
- int head[MAX];
- int visit[MAX];
-
- struct EDGE
- {
- int to;
- int next;
- int wei;
- }edge[MAX];
-
- void add(int u, int v, int w)
- {
- cnt++;
- edge[cnt].wei = w;
- edge[cnt].to = v;
- edge[cnt].next = head[u];
- head[u] = cnt;
- }
-
- int main()
- {
- int i;
- int u, v, w;
- cin >> n >> m >> s;
-
- for (i = 1; i <= n; i++)
- ans[i] = INT_MAX;
- ans[s] = 0;
-
- for (i = 1; i <= m; i++)
- {
- cin >> u >> v >> w;
- add(u, v, w);
- }
-
- priority_queue
int, int> >que;//距离,点 - que.push({0, s});
-
- while (!que.empty())
- {
- int qh = que.top().first;
- int h = que.top().second;
- que.pop();/*记得pop()!!!!!!!!!*/
-
- if (visit[h] == 0)
- {
- visit[h] = 1;
- for (i = head[h]; i != 0; i = edge[i].next)//不断找下一个儿子,直到找完
- {
- if (ans[edge[i].to] > ans[h] + edge[i].wei)
- {
- ans[edge[i].to] = ans[h] + edge[i].wei;
- if (visit[edge[i].to] == 0)
- que.push({ -ans[edge[i].to], edge[i].to });
-
- }
- }
- }
- }
-
- for (i = 1; i <= n; i++)
- cout << ans[i] << ' ';
- cout << endl;
- return 0;
- }
-
-
- //floyd算法
- //要注意中转点,可以直接i到j,也可以i->k,k->j,因此要比较两个数据的大小,最后表中的是最短路径
- //注意是无向图
-
- #include
-
- int main()
- {
- int n, m, i, j, u, v, w;
- long long board[105][105] = { 0 };//存最短路径
-
-
-
- cin >> n >> m;
-
- for (i = 1; i <= n; i++)
- {
- for (j = 1; j <= n; j++)
- {
- if (i == j)
- board[i][j] = 0;
- else
- board[i][j] = INT_MAX;
- }
- }
-
- for (i = 1; i <= m; i++)
- {
- cin >> u >> v >> w;
- if (w < board[u][v])
- board[u][v] = w;
- if (w < board[v][u])
- board[v][u] = w;
- }
-
- int k;
- for (k = 1; k <= n; k++)//把k当中转点,注意是放在i,j循环的外面
- {
- for (i = 1; i <= n; i++)//行,列
- {
- if (i == k)
- continue;
- for (j = 1; j <= n; j++)
- {
- if (j == k)
- continue;
-
- if (i == j)
- continue;
-
- if (board[i][k] != INT_MAX && board[k][j] != INT_MAX)
- board[i][j] = min(board[i][j], board[i][k] + board[k][j]);
-
- }
- }
- }
-
- for (i = 1; i <= n; i++)
- {
- for (j = 1; j <= n; j++)
- {
- cout << board[i][j] << ' ';
- }
- cout << endl;
- }
- return 0;
- }
恭喜你啦,今天又进步了一点点~