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才是王道!