一、Prim算法

    参考之前的博文:http://www.cnblogs.com/Oloo/articles/3631631.html

 二、问题描述

     24851258题目基本一致,唯一的区别就是2485需要注意的一个地方,不然会耗时很长,详见下面的注意。

     3026题相比上两题来说,多了一个困难就是构造图,边的权重需要我们想办法求出来。参见下面的问题分析。

     POJ 2485http://poj.org/problem?id=2485

     POJ 1258http://poj.org/problem?id=1258

     POJ 3026http://poj.org/problem?id=3026

     前两道题题意一看就知道是MST,后一道题想一下也就是知道是MST。题意就不赘述了。

三、问题分析 

     MST需要分析的问题,之前的博文已经分析过了。这里只分析3026中边权重求解。

     答:看到测试样例,我们第一反应就是迷宫题,迷宫题离不开搜索。后面看到从S出发,要求找到所有的A,并且,在初始点和A点处可以分支,并且要求所有分支的路径和最短,这就可以将这个问题看做MST问题。在使用Prim之前,目前我们需要解决的问题就剩下了边权重的计算。我们分析之后,清楚我们要知道任意一点到其他点的距离。于是立马可以想到可以使用BFS来解决。

 四、程序实现

POJ 1258

 

 1 #include<iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 #define INF  100000000
 5 
 6 int N; //#vallege
 7 int edges[102][102];
 8 int values[102];
 9 
10 void input()
11 {
12     for(int i = 0;i < N;i++)
13         for(int j = 0;j < N;j++)
14             scanf("%d" , &edges[i][j]);
15     for(int i = 0;i < N;i++)  values[i] = edges[0][i];
16 }
17 
18 int MST_Prim()
19 {
20    int res = 0;
21    for(int k = 0; k < N;k++)
22    {
23        int index = -1;int min = INF;
24        for(int i = 0;i < N;i++)
25        {
26            if(min > values[i] && values[i] >= 0)
27            {
28                min = values[i];
29                index = i;
30            }
31        }
32        values[index] = -1;
33        res += min;
34        for(int j = 0;j < N;j++)
35            if(edges[index][j] != 0 && edges[index][j] < values[j])
36                values[j] = edges[index][j];
37    }
38    return res;
39 }
40 int main()
41 {
42     while(cin >> N)
43     {
44         input();
45         cout<<MST_Prim()<<endl;
46     }
47     return 0;
48 }
View Code

 

POJ 2485

 

 1 #include<iostream>
 2 #include <cstdio>
 3 using namespace std;
 4 #define INF  100000000
 5 
 6 int N; //#vallege
 7 int edges[502][502];
 8 int values[502];
 9 
10 void input()
11 {
12     scanf("%d" , &N);
13     for(int i = 0;i < N;i++)
14         for(int j = 0;j < N;j++)
15             scanf("%d" , &edges[i][j]);
16     for(int i = 0;i < N;i++)  values[i] = edges[0][i];
17 }
18 
19 int MST_Prim()
20 {
21    int res = 0;
22    for(int k = 0; k < N;k++)
23    {
24        int index = -1;int min = INF;
25        for(int i = 0;i < N;i++)
26        {
27            if(min > values[i] && values[i] >= 0)
28            {
29                min = values[i];
30                index = i;
31            }
32        }
33        values[index] = -1;
34        if(res < min) res = min;
35        for(int j = 0;j < N;j++)
36            if(values[j] >= 0 && edges[index][j] < values[j])
37                values[j] = edges[index][j];
38    }
39    return res;
40 }
41 int main()
42 {
43     int T;
44     scanf("%d" , &T);
45     if(T != 0)
46         while(T--)
47         {
48             input();
49             cout<<MST_Prim()<<endl;
50         }
51     return 0;
52 }
View Code

 

POJ 3026

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<queue>
  4 using namespace std;
  5 #define INF 10000000
  6 
  7 struct point
  8 {
  9     int px,py;
 10     int d;
 11 } points[102];
 12 
 13 int x,y,num;//input y行x列 aliens'num
 14 //****BFS*****
 15 char map[52][52];//储存迷宫地图
 16 int visit[52][52];
 17 queue<point> q;//BFS
 18 int flag[552];
 19 int direct[4][2]  = {{1,0},{0,1},{-1,0},{0,-1}};
 20 //*****Prim*****
 21 int edges[102][102];//记录edges[i]记录i到其他所有点的距离
 22 int values[102];//Prim中点权重记录
 23 
 24 void input()
 25 {
 26     num = 0;
 27     for(int i = 0;i < y;i++)
 28     {
 29         gets(map[i]);
 30         for(int j = 0;j < x;j++)
 31             if(map[i][j] == 'A' || map[i][j]=='S')
 32             {    
 33                 points[num].px = i;
 34                 points[num].py = j;
 35                 points[num].d = 0;
 36                 flag[i*10+j] = num;
 37                 values[num] = INF;
 38                 if(map[i][j] == 'S') values[num] = 0;
 39                 num++;
 40             }
 41     }
 42 }
 43 
 44 void BFS(int u)
 45 {
 46     for(int i = 0;i < num;i++)
 47         points[i].d = 0;
 48     point t;int time = 0;
 49     q.push(points[u]);
 50     while(!q.empty())
 51     {
 52         point p = q.front();
 53         q.pop();
 54         //判断是否为A或者S
 55         if(map[p.px][p.py] == 'A' || map[p.px][p.py]=='S')
 56         {
 57             edges[u][flag[p.px*10+p.py]] = p.d;
 58             time++;
 59         }
 60         visit[p.px][p.py] = 1;
 61         //将合法的四个方向压入q
 62         for(int i = 0;i < 4;i++)
 63         {
 64             int xx = p.px + direct[i][0];
 65             int yy = p.py + direct[i][1];
 66             if(map[xx][yy] != '#' && !visit[xx][yy])
 67             {
 68                 visit[xx][yy] = 1; //这句话导致了TLE
 69                 t.px = xx;
 70                 t.py = yy;
 71                 t.d = p.d+1;
 72                 q.push(t);
 73             }
 74         }
 75     }
 76 }
 77 
 78 void countEdges()
 79 {
 80     for(int i = 0; i < num;i++)
 81     {
 82         memset(visit , 0 ,sizeof(visit));
 83         BFS(i);
 84     }
 85 }
 86 
 87 int MST_Prim()
 88 {
 89     int sum = 0;
 90     for(int k = 0;k < num;k++)
 91     {
 92         int index = -1;int min = INF;
 93         for(int i = 0;i < num;i++)
 94             if(values[i] >= 0 && min > values[i])
 95             {
 96                 min = values[i];
 97                 index = i;
 98             }
 99         values[index] = -1;
100         sum += min;
101         for(int i = 0;i < num;i++)
102             if(edges[index][i] != 0 && edges[index][i] < values[i])
103                 values[i] = edges[index][i];
104     }
105     return sum;
106 }
107 
108 int main()
109 {
110     int T = 0;char c[51];
111     cin >> T;
112     while(T--)
113     {
114         cin >> x >> y;
115         gets(c);
116         input();
117         countEdges();
118         cout<<MST_Prim()<<endl;
119     }
120     return 0;
121 }
View Code

 

 五、注意

     1、 POJ 2485中在接收输入的时候,第一次使用了cin,结果时间惨不忍睹,后来看到题目里的HINT之后,使用了scanf,发现确实快,后来上网看了一下,scanf貌似确实比cin快,cin貌似要同步什么东东,导致了本来比scanf快的cin变慢了,可以用一条代码取消同步,将cin变快,我只能表示,之前一直写java,做androidweb开发的孩子对C++的各种机制不是很了解,这里做一个备注吧,不再深究了。

     2、 POJ 3026,由上面的问题分析知道,我们可以使用BFS+MST-PRIM来解决,这里记个小备注,我在使用BFS的时候翻了一个低级的错误,那就是将邻接的点压入队列的时候,忘了将其标志位置位,导致了BFS运行异常慢。

 

     3POJ 3026,输入数据存在trick,会多出很多的空格,注意使用gets()就好

 

 六、感想

       自己通过自己独立分析问题,自己独立编程实现,最后这个题目AC,这个节奏还是很好的~

       最后,YZY,我想你!

 

 

 

 

 

 

 

 

posted on 2014-04-01 10:24  Oloo  阅读(151)  评论(0)    收藏  举报