CSU 1307 City Tour kruskal + dijkstra
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1307
题意:
找一条路径
1.这条路径中的最大的边一定要尽可能的小
2.满足1的情况下即最大的边相同的时候在找最短路径。
坑爹:
一开始只用最小生成树做,发现如果给的边的权值都一样的话,那你并查集建图完全就跟你输入的顺序
有关,权值都一样的话,并起来的边未必是你最短路要走的边。
找那个最大的边的时候我用递归来找最大的边中间可能有错误,现在还是不知道为什么。
解法:
不用DFS来找最大的边,因为kruskal中加的边是经过排序的,所以只要加到起点和终点连通的
时候就停止了,并返回那个值,这个值就是满足题意中1的那个最大边(k),然后再用dijkstra来找最短路径,
只要在松弛操作中加一个松弛的边不能超过k的条件就可以了。

1 #include<iostream> 2 #include<math.h> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 7 const int maxn = 50000 +10; 8 const int INF = 0x3fffffff; 9 10 struct edge 11 { 12 int start; 13 int end; 14 int values; 15 friend bool operator < (struct edge a,struct edge b) 16 { 17 return a.values < b.values; 18 } 19 }; 20 struct edge num[maxn]; 21 int map[2010][2010]; 22 int father[maxn]; 23 int Rank[maxn]; 24 int dis[maxn]; 25 bool visit[maxn]; 26 int Max; 27 int ans; 28 int ANS; 29 int N; 30 int M; 31 int A; 32 int B; 33 34 void Make_Set(int x) 35 { 36 father[x] = x ; 37 Rank[x] = 0 ; 38 dis[x] = INF; 39 } 40 41 int find_root(int x) 42 { 43 if(father[x] == x) 44 { 45 return x; 46 } 47 else 48 { 49 return father[x] = find_root(father[x]); 50 } 51 } 52 53 void Union(int a,int b) 54 { 55 int roota; 56 int rootb; 57 roota = find_root(a) ; 58 rootb = find_root(b) ; 59 60 if(roota == rootb ) 61 { 62 return; 63 } 64 65 if(Rank[roota] > Rank[rootb] ) 66 { 67 father[rootb] = roota; 68 } 69 else if(Rank[roota] < Rank[rootb] ) 70 { 71 father[roota] = rootb; 72 } 73 else 74 { 75 father[roota] = rootb; 76 Rank[rootb] ++; 77 } 78 } 79 80 int kruskal() 81 { 82 int sum=0; 83 int count=0; 84 int i; 85 sort(num,num+M); 86 for(i=0; i<M && count<=N-1; i++) 87 { 88 int a; 89 int b; 90 a=num[i].start; 91 b=num[i].end; 92 if(find_root(a)!=find_root(b)) 93 { 94 Union(a,b); 95 sum+=num[i].values; 96 count++; 97 if(find_root(A) == find_root(B)) 98 { 99 return num[i].values; 100 } 101 } 102 } 103 return sum; 104 } 105 106 107 void dijkstra(int begin,int end,int no) 108 { 109 int i; 110 dis[begin] = 0; 111 for(i=0; i<N; i++) 112 { 113 int min = INF; 114 int min_j = -1; 115 int j; 116 for(j=1; j<=N; j++) 117 { 118 if(!visit[j] && min > dis[j]) 119 { 120 min = dis[j]; 121 min_j = j; 122 } 123 } 124 if(min_j == -1) 125 { 126 break; 127 } 128 visit[min_j] = true; 129 for(j=1; j<=N; j++) 130 { 131 if(dis[j] > dis[min_j] + map[min_j][j] && map[min_j][j] <= no) 132 { 133 dis[j] = dis[min_j] + map[min_j][j]; 134 } 135 } 136 } 137 } 138 139 int main() 140 { 141 while(cin>>N>>M>>A>>B) 142 { 143 int i; 144 Max = 0; 145 ans = 0; 146 ANS = 0; 147 memset(visit,0,sizeof(visit)); 148 int j; 149 for(i=0; i<maxn; i++) 150 { 151 Make_Set(i); 152 } 153 for(i=0; i<2010; i++) 154 { 155 for(j=0; j<2010; j++) 156 { 157 map[i][j] = INF; 158 } 159 } 160 for(i=0; i<M; i++) 161 { 162 int start; 163 int end; 164 int values; 165 cin>>start>>end>>values; 166 num[i].start = start; 167 num[i].end = end; 168 num[i].values = values; 169 if(map[start][end] > values) 170 { 171 map[start][end] = map[end][start] = values; 172 } 173 } 174 int MAX = kruskal(); 175 dijkstra(A,B,MAX); 176 cout<<dis[B]<<endl; 177 } 178 return 0; 179 } 180 181 /* 182 183 4 4 2 3 184 1 4 5 185 1 2 100 186 2 3 10 187 1 3 10 188 189 3 3 1 2 190 1 3 20 191 3 2 20 192 1 2 20 193 194 5 5 1 4 195 1 2 20 196 2 3 20 197 3 4 20 198 5 4 20 199 1 5 20 200 */