Prim的算法不适用于某种实现

时间:2018-03-14 09:54:32

标签: c++ algorithm graph

我有两个类似的Prim算法的C ++实现用于最小生成树,但其中一个适用于所有情况,而另一个在某些情况下失败。区别在于优先级队列中使用的比较方法。 这是在一些情况下失败的(它使用结构函数来比较给定拱的成本):

#include <iostream>
#include <queue>
#include <vector>
#include <math.h>``
#include <fstream>
using namespace std;

#define NMax 200005
#define oo (1 << 30)

ifstream fin("apm.in");
ofstream fout("apm.out");

int T[NMax], n, m, C[NMax];
bool inmst[NMax];
struct comp{
    bool operator()(int x, int y)
    {
        return C[x] > C[y];
    }
};
vector <pair <int, int> > G[NMax];
priority_queue<int, vector <int>, comp> pq;

void Prim()
{
    for(int i = 1; i <= n; i++)
        C[i] = oo;
    pq.push(1);
    C[1] = 0;
    while(!pq.empty())
    {
        int nod = pq.top();
        pq.pop();
        inmst[nod] = 1;
        for(int i = 0; i < G[nod].size(); i++)
        {
            int v = G[nod][i].first;
            int c = G[nod][i].second;
            if(!inmst[v] && C[v] >= c)
            {
                C[v] = c;
                pq.push(v);
                T[v] = nod;
            }
        }
    }
}

int main()
{
    fin >> n >> m;
    for(int i = 1; i <= m; i++)
    {
        int x, y, c;
        fin >> x >> y >> c;
        G[x].push_back(make_pair(y, c));
        G[y].push_back(make_pair(x, c));
    }
    Prim();
    int ct = 0;
    for(int i = 1; i <= n; i++)
        ct += C[i];
    fout << ct << "\n" << n-1 << "\n";
    for(int i = 1; i <= n; i++)
    {
        if(T[i] == 0) continue;
        fout << i << " " << T[i] << "\n";
    }
}

这是每次都成功的(它在优先级队列中使用更大的并且存储与节点相关的成本和节点本身在队列中):

#include <iostream>
#include <queue>
#include <vector>
#include <math.h>
#include <fstream>
using namespace std;

#define NMax 200005
#define oo (1 << 30)
typedef pair<int, int> iPair;

ifstream fin("apm.in");
ofstream fout("apm.out");

int T[NMax], n, m, C[NMax];
bool inmst[NMax];
struct comp{
    bool operator()(int x, int y)
    {
        return C[x] < C[y];
    }
};
vector <pair <int, int> > G[NMax];
priority_queue< pair<int, int>, vector <pair<int, int> > , greater<pair<int, int> > > pq;

void Prim()
{
    for(int i = 1; i <= n; i++)
        C[i] = oo;
    pq.push((make_pair(0, 1)));
    C[1] = 0;
    while(!pq.empty())
    {
        int nod = pq.top().second;
        pq.pop();
        inmst[nod] = 1;
        for(int i = 0; i < G[nod].size(); i++)
        {
            int v = G[nod][i].first;
            int c = G[nod][i].second;
            if(!inmst[v] && C[v] > c)
            {
                C[v] = c;
                pq.push(make_pair(C[v], v));
                T[v] = nod;
            }
        }
    }
}

int main()
{
    fin >> n >> m;
    for(int i = 1; i <= m; i++)
    {
        int x, y, c;
        fin >> x >> y >> c;
        G[x].push_back(make_pair(y, c));
        G[y].push_back(make_pair(x, c));
    }
    Prim();
    int ct = 0;
    for(int i = 1; i <= n; i++)
        ct += C[i];
    fout << ct << "\n" << n-1 << "\n";
    for(int i = 1; i <= n; i++)
    {
        if(T[i] == 0) continue;
        fout << i << " " << T[i] << "\n";
    }
}

为什么第一个没有按预期工作,如何在仍然使用struct函数和我已经拥有的代码基础的情况下更改它?我尝试了类似于Dijkstra算法的实现。

程序从文件中读取节点和拱门的数量以及所有给定的拱门,并且它应该以任何顺序显示生成树的最小成本,拱门数量和拱门。

我在第一次实施时失败的例子大小非常不正常,我不知道他们是否会有任何帮助:

apm.in:

164 531
155 74 113
73 15 817
38 87 -153
92 100 699
125 114 -210
5 50 -29
1 4 335
11 39 846
112 59 -745
157 86 -146
92 47 397
146 48 -614
81 123 539
8 36 -799
39 17 175
55 36 -133
14 129 809
134 107 948
153 97 -428
144 73 -975
31 41 293
76 95 -550
111 96 -906
132 54 35
19 36 -627
142 31 -949
127 52 -363
44 17 -913
141 69 36
163 2 -610
17 12 -187
65 41 941
160 39 931
69 127 966
98 128 528
144 145 354
49 86 -201
7 102 569
113 31 -151
155 139 752
13 94 -659
140 69 672
32 8 -945
72 19 -592
104 68 -631
5 87 -760
37 58 -211
32 74 134
88 60 622
128 77 -480
4 20 151
38 66 823
133 41 886
128 58 -522
115 68 403
62 128 379
24 156 3
152 22 -630
126 160 322
61 16 852
57 69 -650
126 99 371
87 54 -659
101 93 -44
4 22 899
128 16 222
96 132 -523
67 74 993
143 110 -346
128 9 -892
146 86 -773
14 8 306
114 156 116
91 77 -581
44 95 978
89 38 609
147 139 -486
67 34 -952
119 36 829
44 90 653
1 164 -197
77 157 -273
7 130 606
3 143 701
37 91 363
44 18 -814
53 34 -170
124 39 -384
38 80 -51
72 4 30
133 59 -53
121 10 676
20 142 967
159 84 -456
118 110 75
68 75 828
154 91 -83
94 128 -740
22 72 269
1 81 -371
58 154 98
73 146 -240
11 6 -254
80 62 -70
72 156 611
119 118 990
109 23 -67
103 97 -281
6 135 388
116 159 -948
1 50 -551
31 60 -577
52 47 -514
164 91 562
113 112 178
45 106 -667
160 22 952
17 156 748
125 34 36
94 93 440
139 117 890
43 144 -179
91 60 346
85 96 853
118 156 -991
67 107 718
60 89 649
17 28 -105
64 47 666
26 136 -174
31 147 835
79 115 -235
106 66 693
8 74 107
162 136 712
83 116 506
82 139 489
110 114 -299
96 69 -94
19 129 -361
30 129 612
122 91 -571
62 2 -318
38 143 662
117 142 -34
91 124 385
112 50 -460
14 81 405
129 145 227
71 106 -774
27 15 -339
157 85 251
146 84 726
127 46 -711
95 134 175
134 51 103
31 154 661
95 150 56
164 27 -845
31 127 -452
46 29 -264
74 102 -477
72 39 320
89 23 -811
12 83 -672
68 136 194
82 90 -326
52 81 819
109 47 -204
148 24 870
146 141 148
83 158 -198
77 9 -351
64 25 575
114 28 -992
29 139 630
21 130 -979
153 104 611
80 162 217
155 74 768
2 51 -643
75 97 -706
124 62 -69
36 135 -181
100 43 -163
146 129 54
126 106 799
15 155 907
125 153 658
85 51 702
112 95 80
149 84 -782
46 105 859
69 73 280
98 150 11
60 93 -997
82 134 -786
20 40 -166
134 90 -810
93 76 893
100 51 -161
43 92 314
162 28 525
121 141 -953
30 58 991
97 100 -890
54 23 314
63 92 -480
97 155 -736
29 136 -817
64 86 -424
86 53 613
96 38 -4
57 65 -789
8 6 -586
18 145 -959
136 19 -497
74 86 -895
7 155 -281
43 6 -814
43 69 361
134 141 257
67 46 -326
111 73 -249
11 13 -581
98 143 -909
133 78 -551
83 25 325
93 162 -503
138 31 -386
161 92 135
84 79 -80
12 108 41
86 158 109
71 3 334
27 62 -517
59 15 613
46 63 -316
74 39 996
37 11 -438
38 102 369
15 129 313
131 6 -841
152 109 -529
124 53 878
35 78 -994
116 117 -312
47 109 -12
47 36 534
84 63 -626
152 142 667
87 79 -201
52 22 -518
99 103 -434
139 53 262
162 1 -524
120 69 836
131 93 368
155 135 5
133 117 -818
59 15 854
37 139 931
111 8 -15
92 58 411
126 19 789
111 12 763
66 147 605
20 142 -446
156 163 -566
137 36 -350
127 156 -307
49 22 376
124 24 -863
36 161 175
63 27 -687
5 29 -375
27 69 -260
24 149 447
141 117 32
58 64 239
87 149 -919
65 101 -807
127 117 237
145 44 -731
32 74 535
142 13 -869
49 5 315
152 105 -747
10 133 -232
69 98 -253
134 86 458
129 48 -322
121 132 46
64 15 -216
103 38 -530
63 17 -871
69 38 -577
55 106 141
111 90 583
138 100 -478
67 43 -608
141 88 921
45 55 596
155 91 338
128 3 532
28 124 -839
134 101 240
36 41 -888
3 156 -139
79 151 446
41 150 978
160 3 70
5 45 -597
89 103 -849
123 56 -820
16 123 779
114 89 -534
160 147 -359
52 140 239
142 80 66
124 66 -18
89 23 945
162 108 -353
151 143 -912
68 121 656
23 122 730
17 8 -81
87 130 44
116 158 -234
16 123 430
66 130 -398
29 65 -844
105 43 -854
84 99 -730
107 162 729
128 153 175
146 13 538
135 43 -753
93 123 996
23 3 -436
45 133 -203
151 132 931
49 159 -358
147 120 -274
132 131 -192
94 141 -758
19 153 946
155 33 284
85 18 646
69 148 -720
142 125 965
80 63 -96
29 140 -129
116 50 -111
38 124 -750
156 102 -674
39 67 -459
50 150 -261
110 29 904
11 83 -520
58 65 449
34 144 -362
103 76 567
97 85 322
151 76 118
61 58 -636
7 143 535
61 26 40
10 57 -155
120 33 -871
28 53 -176
57 86 -602
161 92 -96
69 151 555
49 17 876
43 71 -91
47 118 -191
70 49 576
102 139 -920
60 153 873
80 124 222
30 20 -147
37 158 587
65 9 314
46 69 957
117 16 -831
74 106 -756
95 92 -222
52 147 310
2 61 -427
138 21 -256
113 94 273
162 105 -53
40 80 572
21 143 386
154 115 229
97 126 362
106 40 -164
60 100 -405
29 109 -506
133 35 -867
114 70 -169
132 46 -145
161 133 434
94 47 -939
86 91 543
110 155 -277
20 162 -683
32 145 304
135 124 -23
5 123 283
11 65 -858
31 128 223
54 97 585
8 93 688
91 58 -974
123 97 931
140 61 822
19 13 69
161 162 976
126 115 887
47 84 -502
12 157 -824
135 98 420
114 6 -605
66 138 -354
70 138 -596
56 87 145
37 159 -207
78 136 -573
49 57 271
154 14 859
103 139 -848
32 105 -927
163 126 -935
49 19 262
14 108 408
164 145 -612
37 135 -454
68 20 892
78 164 470
24 109 -598
70 53 -403
71 148 -983
92 46 851
26 34 -602
88 47 -667
66 59 750
142 99 319
43 57 967
109 17 654
85 108 -947
74 33 694
150 83 -845
129 7 -37
65 70 -668
4 102 771
158 69 -615
85 148 225
12 55 172
7 41 -83
123 103 937
110 137 -36
42 131 -392
153 18 -844
86 94 -404
77 44 -307
18 114 -372
75 115 99
53 4 -472
140 159 -844
46 67 -991
84 162 599
91 106 406
149 108 -811
142 22 -653
136 44 496
131 43 -2
122 37 375
103 109 -692
26 58 -822
84 128 -967
71 53 -162
74 18 -123
145 103 722
65 99 -961
56 15 -908
44 147 176
41 133 -145
96 63 915
35 20 -106
122 73 -845
11 150 917
5 105 -361
119 44 -261
27 76 215
129 11 -102
157 140 338
160 120 958
28 131 -194
36 106 -468
130 52 679
16 76 -514
151 156 236
2 137 -335
112 80 724
35 78 -535
44 121 119
62 59 -379
110 141 780
52 37 342
29 33 -49
89 7 828
87 131 171
44 130 419
86 45 438
103 128 558
24 129 -565
86 99 -758
51 110 -571
117 94 476
61 78 -875
127 101 -359
146 40 -871
87 48 -600
97 149 -165
3 58 507
88 37 -764
51 43 918
41 76 10
13 88 -835

apm.ok:

-105854
163
60 93
35 78
114 28
46 67
118 156
71 148
21 130
144 73
91 58
84 128
65 99
18 145
121 141
67 34
142 31
116 159
85 108
32 8
94 47
163 126
32 105
102 139
87 149
44 17
151 143
98 143
56 15
111 96
74 86
128 9
97 100
36 41
61 78
120 33
63 17
146 40
142 13
133 35
124 24
11 65
105 43
89 103
103 139
150 83
164 27
122 73
140 159
153 18
29 65
131 6
28 124
13 88
117 16
12 157
26 58
123 56
133 117
29 136
43 6
44 18
89 23
149 108
134 90
65 101
8 36
57 65
82 134
149 84
71 106
146 86
88 37
5 87
94 141
86 99
74 106
135 43
38 124
152 105
112 59
94 128
97 155
84 99
69 148
127 46
75 97
103 109
63 27
20 162
156 102
12 83
65 70
45 106
88 47
87 54
142 22
2 51
61 58
104 68
152 22
19 36
84 63
158 69
146 48
163 2
67 43
114 6
26 34
24 109
70 138
72 19
91 77
31 60
122 91
51 110
156 163
24 129
1 50
76 95
162 1
96 132
11 83
52 22
27 62
16 76
93 162
147 139
63 92
138 100
53 4
112 50
39 67
159 84
23 3
64 86
70 53
66 130
42 131
1 81
160 147
49 159
66 138
137 36
143 110
27 15
7 155
147 120
119 44
111 73
79 115
10 133
125 114
87 79
113 31
30 20
55 36
80 63
161 92
154 91
134 51
68 136
14 8
83 25
67 107

apm.out:

-105439
163
2 163
3 23
4 53
5 87
6 43
7 155
8 32
9 128
10 133
11 13
12 83
13 142
14 8
15 27
16 117
17 63
18 44
19 36
20 162
21 130
22 142
23 89
24 124
25 83
26 58
27 63
28 114
29 65
30 20
31 60
32 105
33 120
34 67
35 78
36 8
37 88
38 69
39 67
40 146
41 36
42 131
43 105
44 17
45 106
46 67
47 88
48 146
49 159
50 1
51 2
52 22
53 70
54 87
55 36
56 15
57 65
58 61
59 112
60 93
61 78
62 27
63 84
64 86
65 11
66 138
67 43
68 136
69 148
70 65
71 106
72 19
73 122
74 86
75 97
76 16
77 91
78 136
79 87
80 63
81 1
82 134
83 11
84 128
85 108
86 99
87 149
88 13
89 114
90 134
91 58
92 63
93 162
94 47
95 76
96 111
97 100
98 143
99 65
100 138
101 65
102 139
103 89
104 68
105 152
106 74
107 67
108 149
109 103
110 51
111 73
112 50
113 31
114 6
115 79
116 159
117 133
118 156
119 44
120 147
121 141
122 91
123 56
124 28
125 114
126 163
127 46
128 94
129 24
130 66
131 6
132 96
133 35
134 51
135 43
136 29
137 36
138 70
139 103
140 159
141 94
142 31
143 110
144 73
145 18
146 86
147 139
148 71
149 84
150 83
151 143
152 22
153 18
154 91
155 97
156 102
157 12
158 69
159 84
160 147
161 92
162 1
163 156
164 27

2 个答案:

答案 0 :(得分:0)

通过暴露的示例代码,我怀疑比较行为的本质区别。为了证明这种怀疑,我将两个版本的示例代码放入WinMerge并进行比较。他们看起来很相似。所以,我很确定我走在正确的轨道上:

第一个版本使用它进行比较:

struct comp{
    bool operator()(int x, int y)
    {
        return C[x] > C[y];
    }
};

第二个版本使用此代码:

std::greater<pair<int, int> >

重大差异std::greater在比较中考虑 std::pair成员,但第一个样本中的比较函数仅C[x]C[y](但不是xy)。

根据cppreference.com

template< class T1, class T2 >
constexpr bool operator>(const pair<T1,T2>& lhs, const pair<T1,T2>& rhs);

定义为rhs < lhs

template< class T1, class T2 >
constexpr bool operator<(const pair<T1,T2>& lhs, const pair<T1,T2>& rhs);

确实

  

如果lhs.first<rhs.first,则返回true。否则,如果rhs.first<lhs.first,则返回false。否则,如果lhs.second<rhs.second,则返回true。否则,返回false

因此,如果第一个比较类似于第二个比较,则必须将第一个样本的比较仿函数更改为例如:

struct comp{
    bool operator()(int x, int y)
    {
        return x == y ? C[x] > C[y] : x > y;
    }
};

这看起来有点愚蠢,因为x == y肯定会导致C[x] == C[y]。但是,它应该返回与第二个示例代码的std::greater<std::pair<int, int> >完全相同的结果。

关于OP的原始问题,第一个版本实际上可能是正确的(并且还有另一个错误或关于输出的错误期望)。在这种情况下,必须调整第二个样本的比较,例如,介绍一个resp。 std::pair的仿函数:

struct comp{
    bool operator()(
      const std::pair<int, int> &xCx, const std::pair<int, int> &yCy) const
    {
        return xCx.second > yCy.second;
    }
};

由于我不知道Prim的算法,我无法确定哪一个是真正正确的解决方案。 OP可能会留下一个关于此的说明(我很乐意编辑它)。

答案 1 :(得分:0)

每次从u弹出节点priority_queue时,您需要更新C[v],其中v是与u相邻的节点。这些v可能已经在队列中,因此从技术上讲,您间接更新priority_queue中某些元素的值(因为元素的值通过C[]表示)。它会破坏队列的结构并导致错误的答案。

在正确的版本中,您将2 int推入队列,这些值永远不会更改。因此,您没有遇到上述问题。