20151230训练题解(最短路+拓扑排序)

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=103223#problem/B

这道题用经典的dijsktra算法,大概思路就是用dist[x]存储x到已经确定集合的最短路,n次循环到这个这个最小值,然后更新其他点到新集合的最短路即对应的dist[]

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 using namespace std;
 6 const int MAX = 105;
 7 const int INF = 0x3f3f3f3f;
 8 int g[MAX][MAX],dist[MAX],vis[MAX];
 9 int n,m;
10 void dijstra()
11 {
12     memset(vis, 0, sizeof(vis));
13     for(int i = 1; i <= n; i++)
14     {
15         if(g[1][i] != INF)
16             dist[i] = g[1][i];
17         else
18             dist[i] = INF;
19     }
20     dist[1] = 0;
21     vis[1] = 1;
22     int maxn,pos = 1,temp; //pos =1,作为起点
23     for(int i = 1; i <= n; i++)
24     {
25         maxn = INF;
26         for(int j = 1; j <= n; j++)
27         {
28             if(vis[j] == 0 && dist[j] < maxn) //找不到集合的最小距离,mazn
29             {
30                 maxn = dist[j];
31                 temp = j;
32             }
33         }
34         vis[temp] = 1; //把该点加入集合,即设访问为1
35         pos = temp;
36         for(int j = 1; j <= n; j++)
37         {
38             if(vis[j] == 0)   //跟新以pos为起点到集合的距离
39                 dist[j] = min(dist[j], dist[pos] + g[pos][j]);
40         }
41     }
42 }
43 int main()
44 {
45    while(scanf("%d%d", &n,&m) != EOF)
46    {
47        int a,b,c;
48        if(n == 0 || m == 0)
49            break;
50        memset(g, INF, sizeof(g));
51        for(int i = 1; i <= m; i++)
52        {
53            scanf("%d%d%d", &a,&b,&c);
54            if(g[a][b] > c)  //考虑重边,去最小
55                g[a][b] = g[b][a] = c;
56        }
57        dijstra();
58        printf("%d\n",dist[n]);
59    }
60    return 0;
61 }

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=103223#problem/C

拓扑排序就是通过找入度为0的点,找到后更新其他的点入度,然后在找入度为0的点直到没有为0的点,为了便于理解这里直接用两重循环写的,后期大家熟悉了就可以用栈来存入度为0的点

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 int g[550][550];
 7 int indegree[550]; //存入度
 8 int pur[550];
 9 int main()
10 {
11     int n,M,x,y;
12     while(scanf("%d%d",&n,&M) != EOF)
13     {
14         memset(indegree,0,sizeof(indegree));
15         memset(g,0,sizeof(g));
16
17         for(int i = 1;i <= M; i++)
18         {
19            scanf("%d%d",&x,&y);
20            if(g[x][y] == 0)
21            {
22               g[x][y] = 1;
23               indegree[y]++;
24            }
25          }
26          int k=1;
27          for(int i = 1; i <= n; i++)
28          {
29              for(int j = 1; j <= n; j++)
30              {
31                 if(indegree[j] == 0) //找入度为0的点
32                 {
33                     pur[k++] = j;
34                     indegree[j]--;
35                     for(int m = 1; m <= n; m++) //更新
36                     {
37                         if(g[j][m])
38                             indegree[m]--;
39                     }
40                     break;
41                 }
42              }
43          }
44          for(int i = 1; i < n; i++)
45              printf("%d ",pur[i]);
46          printf("%d\n",pur[n]);
47     }
48     return 0;
49 }

找第一题没注意到数据类型,最后可能害不少人浪费了不少时间,sorry...图论题目可能大家没看到,应该数据结构大家也都讲了,但是请大家记住,讲了,听懂了,不一定是真的会,只有AC才是王道!

时间: 2024-10-12 21:12:30

20151230训练题解(最短路+拓扑排序)的相关文章

HDU 3342 Legal or Not (最短路 拓扑排序?)

Legal or Not Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6580    Accepted Submission(s): 3088 Problem Description ACM-DIY is a large QQ group where many excellent acmers get together. It is

[Luogu P3953] 逛公园 (最短路+拓扑排序+DP)

题面 传送门:https://www.luogu.org/problemnew/show/P3953 Solution 这是一道神题 首先,我们不妨想一下K=0,即求最短路方案数的部分分. 我们很容易可以想到一个做法,就是魔改迪杰斯特拉做法: 如果一个点可以更新到达其他点的距离,那个点的方案数就是这个点的方案数:如果一个点所更新出来的距离和之前的相等,那个点的方案数加等当前点的方案数. 用式子可以表现为: f[j]=f[i] (dis[j]>dis[i]+x)   f[j]+=f[i] (dis

BZOJ1880 SDOI2009 Elaxia的路线 最短路+拓扑排序

题意:给定两个点对和一张无向图,求两个点对的最短路中,重边边权和的最大值 题解: 首先从给出的四个点出发跑出到其他所有点的最短路,然后判断哪些边是重边.找出所有重边后,将其构有向图,在该图上用拓扑排序求最长路. 开始的时候枚举每一条边我没有建反向边,而是每次判定的时候互换一下边的始末点看是否合法,结果最后一个点死活过不去.后来上网搜题解才知道,必须建反向边,与原边分别判断.果然偷懒就是不行啊…… #include <cstdio> #include <cstring> #inclu

Luogu P3953【NOIP2017】逛公园【最短路+拓扑排序+动态规划】

题目描述 策策同学特别喜欢逛公园.公园可以看成一张NN个点MM条边构成的有向图,且没有 自环和重边.其中1号点是公园的入口,NN号点是公园的出口,每条边有一个非负权值, 代表策策经过这条边所要花的时间. 策策每天都会去逛公园,他总是从1号点进去,从NN号点出来. 策策喜欢新鲜的事物,它不希望有两天逛公园的路线完全一样,同时策策还是一个 特别热爱学习的好孩子,它不希望每天在逛公园这件事上花费太多的时间.如果1号点 到NN号点的最短路长为dd,那么策策只会喜欢长度不超过d + Kd+K的路线. 策策

NOIP2017 Day1 T3 逛公园(最短路+拓扑排序+DP)

神tm比赛时多清个零就有60了T T 首先跑出1起点和n起点的最短路,因为k只有50,所以可以DP.设f[i][j]表示比最短路多走i的长度,到j的方案数. 我们发现如果在最短路上的和零边会有后向性,怎么办呢?拓扑排序. 把最短路上的点和零边的点拉出来跑拓扑排序,如果有零环的话必定度数不为0,而且要注意零环必须在<=最短路+k的路径上才输出-1,这个就用刚刚跑出来的1起点到n起点的最短路来判断就好了. 然后先按拓扑序DP出i相同的,然后再DP不在最短路上或者零边的. #include<iost

1880. [SDOI2009]Elaxia的路线【最短路+拓扑排序】

Description 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间.Elaxia和w**每天都要奔波于宿舍和实验室之间,他们 希望在节约时间的前提下,一起走的时间尽可能的长. 现在已知的是Elaxia和w**所在的宿舍和实验室的编号以及学校的地图:地图上有N个路 口,M条路,经过每条路都需要一定的时间. 具体地说,就是要求无向图中,两对点间最短路的最长公共路径. Input 第一行:两个整数N和M(含义如题目描述).

【CSP模拟赛】益智游戏(最短路&amp;拓扑排序)

题目描述 小P和小R在玩一款益智游戏.游戏在一个正权有向图上进行. 小P 控制的角色要从A 点走最短路到B 点,小R 控制的角色要从C 点走最短路到D 点. 一个玩家每回合可以有两种选择,移动到一个相邻节点或者休息一回合. 假如在某一时刻,小P 和小R 在相同的节点上,那么可以得到一次特殊奖励,但是在每 个节点上最多只能得到一次. 求最多能获得多少次特殊奖励 输入格式 第一行两个整数n,m 表示有向图的点数和边数. 接下来m 行每行三个整数xi,yi,li,表示从xi 到yi 有一条长度为li

HDU 5638 拓扑排序+优先队列

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5638 题意: 给你一个DAG图,删除k条边,使得能个得到字典序尽可能小的拓扑排序 题解: 把拓扑排序的算法稍微改一下,如果某个顶点的入度小于k也把它加到优先队列里面去. k减小后队列里面会有些点不满足<=k,直接踢出来就好了. 代码: #include<iostream> #include<cstring> #include<cstdio> #include<

bzoj 4010: [HNOI2015]菜肴制作(优先队列+拓扑排序)

4010: [HNOI2015]菜肴制作 Time Limit: 5 Sec  Memory Limit: 512 MB Submit: 1199  Solved: 583 [Submit][Status][Discuss] Description 知名美食家小 A被邀请至ATM 大酒店,为其品评菜肴. ATM 酒店为小 A 准备了 N 道菜肴,酒店按照为菜肴预估的质量从高到低给予 1到N的顺序编号,预估质量最高的菜肴编号为1.由于菜肴之间口味搭配的问题, 某些菜肴必须在另一些菜肴之前制作,具体