中国郵路問題のプログラミングの解
9771 ワード
中国郵路問題(Chinese Postman Problem)は非常に古典的な図論問題である.郵便配達員が手紙を送り、彼が配達を担当しているすべての街(すべての街が双方向に通行し、すべての街が一度以上通過できる)を歩き終え、任務を終えて郵便局に戻り、どのようなルートで歩けば、彼が歩いた道のりが最も短いのだろうか.この問題を図論に抽象化する言語は,連通図を与え,各エッジの重み値が街の長さである場合,本問題は図中に回路を求め,回路の総重み値を最小にすることに変換される.
街の連通図がオーラ図であれば、図中のオーラ戻り路を1本だけ要求すればよい.そうでなければ、郵便配達員が任務を遂行するには、いくつかの街を何度も繰り返さなければならない.1回繰り返すと平行なエッジが追加され、元の対応する図形が多重図になります.追加する平行エッジの総重み値が最小であればよいだけです.そこで,我々の問題は,奇度数ノードを有する重み付き連通図において,新しい図が奇度数ノードを含まず,増加したエッジの総重み値が最小になるように,いくつかの平行エッジを増加させることに転化した.
増加したエッジの総重み値の最小を求めるスキームは,すべての奇度頂点(偶数個)を2つのグループに分け,各グループの2つの点に対して最短経路を求め,さらに各グループの総重み値を求める必要がある.すべてのグループの状況に対して、最小の重み値を見つけるのが最適です.
以下、ソースコードを直接アップします.
転載先:https://www.cnblogs.com/guocai/archive/2012/07/08/2581979.html
街の連通図がオーラ図であれば、図中のオーラ戻り路を1本だけ要求すればよい.そうでなければ、郵便配達員が任務を遂行するには、いくつかの街を何度も繰り返さなければならない.1回繰り返すと平行なエッジが追加され、元の対応する図形が多重図になります.追加する平行エッジの総重み値が最小であればよいだけです.そこで,我々の問題は,奇度数ノードを有する重み付き連通図において,新しい図が奇度数ノードを含まず,増加したエッジの総重み値が最小になるように,いくつかの平行エッジを増加させることに転化した.
増加したエッジの総重み値の最小を求めるスキームは,すべての奇度頂点(偶数個)を2つのグループに分け,各グループの2つの点に対して最短経路を求め,さらに各グループの総重み値を求める必要がある.すべてのグループの状況に対して、最小の重み値を見つけるのが最適です.
以下、ソースコードを直接アップします.
#include
#include
#include
#include
#include
using namespace std;
#define MAX_NODE 26 //
#define COST_NO_LINK INT_MAX // INT_MAX
int Graph[MAX_NODE][MAX_NODE];
int Cost[MAX_NODE][MAX_NODE];
int V_dingdianshu, E_bianshu, Start_Point; // , ( 0 )
int Odd_Grouping[MAX_NODE]; // 0 , 1 , 2 , 2 , 3 ,……
int Bak_Odd_Grouping[MAX_NODE]; // , , , 。
int SHORTEST_PATH_WEIGHT(COST_NO_LINK); // , , 。 Bak_Odd_Grouping 。
int Dist[MAX_NODE]; // Dijstra , v0 v1 , v0
int ShortCache[MAX_NODE][MAX_NODE]; // Dijstra , v0 v1 , , , , 。
// , Graph Cost
void Input()
{
int i, j;
int m, n;
char cs, cm, cn;
int w;
cout << " :";
cin >> V_dingdianshu;
cout << " :";
cin >> E_bianshu;
cout << " :";
cin >> cs;
Start_Point = cs - 'a';
for(i = 0; i < V_dingdianshu; i++)
{
for(j = 0; j < V_dingdianshu; j++)
{
Graph[i][j] = 0;
ShortCache[i][j] = 0;
Cost[i][j] = COST_NO_LINK;
}
Cost[i][i] = 0; // 0
}
cout << " " << E_bianshu << " ( a ):" << endl;
for(i = 0; i < E_bianshu; i++)
{
cin >> cm >> cn >> w;
m = cm - 'a';
n = cn - 'a';
Graph[m][n] += 1;
Graph[n][m] += 1;
Cost[m][n] = w;
Cost[n][m] = w;
}
}
// G v0 v1 , dist 。 dist ( dist[v] v0 v )
// Cache , , Dist , dist[v] v0 v
// dist[v1], v0 v1
int Dijstra(int v0, int v1, bool useCache)
{
if(useCache && ShortCache[v0][v1] != 0) // ,
{
return ShortCache[v0][v1];
}
int i, s, w, min, minIndex;
bool Final[MAX_NODE];
// ,
for (s = 0; s < V_dingdianshu; s++)
{
Final[s] = false;
Dist[s] = COST_NO_LINK; //
}
// v0 v0 ,
Final[v0] = true;
Dist[v0] = 0;
s = v0; // 0 v0
for (i = 0; i < V_dingdianshu; i++)
{
// 1
for(w = 0; w < V_dingdianshu; w++)
{
if(!Final[w] // w
&& Cost[s][w] < COST_NO_LINK // s
&& Dist[w] > Dist[s] + Cost[s][w]) // s
{
if(Dist[s] + Cost[s][w] <= 0)
{
cout << " 。" << endl;
exit(-1);
}
Dist[w] = Dist[s] + Cost[s][w];
}
}
// 1.5 v1,
if(s == v1)
{
ShortCache[v0][v1] = Dist[s];
ShortCache[v1][v0] = Dist[s];
return Dist[s];
}
// 2
min = COST_NO_LINK;
for(w = 0; w < V_dingdianshu; w++)
{
if(!Final[w] //
&& Dist[w] < min) //
{
minIndex = w;
min = Dist[w];
}
}
s = minIndex;
Final[s] = true;
}
cerr << " 。。。 " << endl;
exit(-1);
}
//
// start ( 0 ),
//
// start :start
bool ConnectivityTest(int start, bool& bNoPoints)
{
set nodeSet; //
vector for_test_nodes; //
int i, j;
set singlePoints; //
//
bool hasEdge = false;
for(i = 0; i < V_dingdianshu; i++)
{
hasEdge = false;
for(j = 0; j < V_dingdianshu; j++) // 0,
{
if (Graph[i][j] > 0)
{
hasEdge = true;
break;
}
}
if (!hasEdge)
{
singlePoints.insert(i);
}
}
bNoPoints = (singlePoints.size() == V_dingdianshu); // bNoPoints
if(singlePoints.find(start) != singlePoints.end()) // start
{
return false;
}
for_test_nodes.push_back(start); //
while(for_test_nodes.size() > 0)
{
int testNode = for_test_nodes.back();
for_test_nodes.pop_back();
for(i = 0; i < V_dingdianshu; i++)
{
if(Graph[testNode][i] > 0)
{
if(nodeSet.insert(i).second)
{
for_test_nodes.push_back(i);
}
}
}
}
for(i = 0; i < V_dingdianshu; i++)
{
if (singlePoints.find(i) == singlePoints.end()
&& nodeSet.find(i) == nodeSet.end())
// , , ,
{
return false;
}
}
return true;
}
// , ,
int OddTest()
{
int i, j, rSum, count;
//
for(i = 0; i < V_dingdianshu; i++)
{
Odd_Grouping[i] = 0; // 0
Bak_Odd_Grouping[i] = 0;
}
count = 0;
for(i = 0; i < V_dingdianshu; i++)
{
rSum = 0;
for(j = 0; j < V_dingdianshu; j++)
{
rSum += Graph[i][j]; // i
}
if(rSum % 2 == 1)
{
Odd_Grouping[i] = 1;
count++;
}
}
return count;
}
void Bak_Grouping()
{
int i;
for(i = 0; i < V_dingdianshu; i++)
{
Bak_Odd_Grouping[i] = Odd_Grouping[i];
}
}
// ,level 2 。
// 。 。
bool Grouping(int level)
{
if(level < 2)
{
cerr << " 2 level 。" << endl;
exit(-1);
}
int i, j, findI = -1;
for(i = 0; i < V_dingdianshu; i++)
{
if(Odd_Grouping[i] == 1)
{
Odd_Grouping[i] = level; // 。
findI = i;
break;
}
}
bool re = true;
if(findI == -1) // , 。
{
int weightSum = 0;
for(i = 2; i < level; i++) // level 2 level-1 , i
{
int index[2];
int *pIndex = index;
for(j = 0; j < V_dingdianshu; j++)
{
if(Odd_Grouping[j] == i)
{
*pIndex = j;
if(pIndex == index + 1) // index
{
break;
}
pIndex++;
}
}
weightSum += Dijstra(index[0], index[1], true); // , , 。 。
}
if(weightSum < SHORTEST_PATH_WEIGHT) // ,
{
Bak_Grouping(); // ,
SHORTEST_PATH_WEIGHT = weightSum;
return true; // ,
}
else
{
return false; // ,
}
}
else if(findI > -1)
{
// , 。
for(/* for */; i < V_dingdianshu; i++)
{
if(Odd_Grouping[i] == 1) //
{
Odd_Grouping[i] = level;
re = Grouping(level + 1);
Odd_Grouping[i] = 1; // ,
}
}
}
else
{
cerr << "findCount " << endl;
exit(-1);
}
if(findI > -1)
{
Odd_Grouping[findI] = 1; // ,
}
return re;
}
void AddShortPath(int from, int to)
{
int i, back;
Dijstra(from, to, false); // , dist
back = to;
while(back != from) // from ... back ... to
{
for(i = 0; i < V_dingdianshu; i++)
{
if(i != back
&& Dist[i] < COST_NO_LINK // from i
&& Dist[back] < COST_NO_LINK // from back
&& Dist[i] + Cost[i][back] == Dist[back]) // from i back from back , i ( , (i,back) , Dist[i] + Cost[i][back] )
{
Graph[i][back]++; //
Graph[back][i]++;
back = i;
break;
}
}
if(i == V_dingdianshu) // : break ++
{
cerr << " , 。。。" << endl;
exit(-1);
}
}
}
// odd
void AddShortPaths()
{
int i, j;
for(i = 0; i < V_dingdianshu; i++)
{
if(Bak_Odd_Grouping[i] > 1)
{
for(j = i + 1; j < V_dingdianshu; j++)
{
if(Bak_Odd_Grouping[j] == Bak_Odd_Grouping[i])
{
AddShortPath(i, j);
break;
}
}
}
}
}
//
void OddDeal()
{
// ,
int oddCount = OddTest();
if(oddCount > 0)
{
if(oddCount % 2 == 1)
{
cerr << " , ?" << endl;
exit(-1);
}
// 。。。
Grouping(2); // odd2
AddShortPaths(); // odd
}
}
/*
Fleury
wi=v0e1v1…eivi , E-{e1,e2,…,ei} ei+1:
1)、 ei+1 vi+1 ;
2)、 , ei+1 Gi=G-{e1,e2,…,ei} 。
3)、 (2) , 。
*/
void Fleury(int start)
{
int i;
int vi = start; // v0e1v1…eivi
bool bNoPoints, bCnecTest;
cout << " :";
while(true)
{
// ei+1
for(i = 0; i < V_dingdianshu; i++)
{
if (Graph[vi][i] > 0)
{
// (vi,i)
Graph[vi][i]--; // Graph , , 。
Graph[i][vi]--;
bCnecTest = ConnectivityTest(i, bNoPoints);
if(!bNoPoints && !bCnecTest) // i, ,
{
Graph[vi][i]++;
Graph[i][vi]++;
continue;
}
// (vi,i)
cout << (char)('a' + vi) << "-" << (char)('a' + i) << " ";
vi = i;
break;
}
}
if (i == V_dingdianshu)
{
cout << endl;
break; //
}
}
}
int main()
{
Input();
bool b;
if(!ConnectivityTest(0, b)) // b , 。
{
cout << " !
";
exit(0);
}
OddDeal(); //
Fleury(Start_Point); //
return 0;
}
転載先:https://www.cnblogs.com/guocai/archive/2012/07/08/2581979.html