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 */
View Code

 

 

posted @ 2013-08-31 20:50  pc....  阅读(309)  评论(0)    收藏  举报