[Swust OJ 767]--将军回家(Dijkstra算法)
题目链接:http://acm.swust.edu.cn/problem/767/
Time limit(ms): 1000 Memory limit(kb): 65535
Description
在涪江河的两边共有n个城市,其中位于一边的城市属于1类城市,另外一边的属于2类城市,(特别的:城市1属于1类,城市2属于2类)。现在知道一些道路的情况,比如知道城市1到城市5之间有一条长度为100的路。将军要从城市1回到城市2的家,他就开始设计回家的线路。回家时由于驾照的关系,只能越过一次涪江河。现在问从城市1到城市2的最短距离,路是双向的。
Input
多组测试数据。
每组数据的第一行输入城市个数N(2<=N<=600),第二行输入城市之间的路的数目M((0<=M<=10000),
接下里M行,输入每条道路的信息,每行S,E,T都是整数,代表城市S和城市E之间有一条长度为T的路。
最后一行N个数只能是1或2代表第i个城市属于哪类。
为了简化题目,我们总认为城市1是属于1类,城市2属于2类 N = 0时表示结束
Output
输出城市1到城市2的最短路径,如果不存在则输出-1
Sample Input
2
1
1 2 100
1 2
3
3
1 2 100
1 3 40
2 3 50
1 2 1
5
5
3 1 200
5 3 150
2 5 160
4 3 170
4 2 170
1 2 2 2 1
0
|
Sample Output
100
90
540
|
解题思路:一个Dijkstra题,注意一类城市,二类城市分属河两岸,且将军只能过河一次优化路径是注意下就OK了
!vis[j] && (v[sign] == 1 || (v[sign] == 2 && v[j] == 2)) && dis[j] > dis[sign] + mpt[sign][j]
基于只能过河一次如果把一二类城市间连通状态改成单向应该也可以,到时有空去试一下Orz~~~
代码如下:
1 #include <stdio.h> 2 #include <string.h> 3 #define inf 0x3f3f3f3f 4 5 int m, n, mpt[605][605], v[605], dis[605], vis[605]; 6 void Dijkstra(){ 7 int i, j, minn, sign; 8 for (i = 2; i <= n; i++) dis[i] = mpt[1][i]; 9 vis[1] = 1; 10 dis[1] = 0; 11 for (i = 2; i <= n; i++){ 12 minn = inf; 13 for (j = 2; j <= n; j++){ 14 if (!vis[j] && minn > dis[j]){ 15 minn = dis[j]; 16 sign = j; 17 } 18 } 19 if (minn >= inf)break; 20 vis[sign] = 1; 21 for (j = 2; j <= n; j++){ 22 if (!vis[j] && (v[sign] == 1 || (v[sign] == 2 && v[j] == 2)) && dis[j] > dis[sign] + mpt[sign][j]) 23 dis[j] = dis[sign] + mpt[sign][j]; 24 } 25 } 26 if (dis[2] >= inf) 27 printf("-1\n"); 28 else 29 printf("%d\n", dis[2]); 30 } 31 32 int main(){ 33 int i, a, b, c; 34 while (~scanf("%d", &n) && n){ 35 scanf("%d", &m); 36 memset(mpt, inf, sizeof(mpt)); 37 memset(vis, 0, sizeof(vis)); 38 for (i = 1; i <= m; i++){ 39 scanf("%d%d%d", &a, &b, &c); 40 if (c >= mpt[a][b])continue; 41 mpt[a][b] = c; 42 mpt[b][a] = c; 43 } 44 for (i = 1; i <= n; i++) scanf("%d", &v[i]); 45 Dijkstra(); 46 } 47 return 0; 48 }
如果这是你所爱的,就不要让自己后悔~~~