题目:http://dsalgo.openjudge.cn/dsmoochw8/4/
做过这道题后,我明白了为何prime算法不可用于DG上的MST求解,并理解了刘朱算法的思想。感谢某匿名同学提供了很多有用的资料和Chong Wang同学的提问。
相应的帖子链接:https://class.coursera.org/dsalgo-001/forum/thread?thread_id=236
mysol:
1.构图(去掉指向顶点0的弧)
2.floodfill判断是否联通图,if not :continue
3.foreach_v if( !visit[v] ): dfs(v)【找环,压缩, 标记】
4.求和
/*
ID:slowlight
PROG:
LANG:C++
DATE:
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define MAXVERTEXES 100
#define MAXEDGES 10000
#define INF 100000000
#define FORI(type, i, limi) for(type i = 0;i < limi;++i)
typedef struct node_type {
int x;
int y;
int pre;
}Node;
Node nodes[MAXVERTEXES + 1];
double cost[MAXVERTEXES + 1][MAXVERTEXES + 1];
bool canReach[MAXVERTEXES + 1][MAXVERTEXES + 1];
int n, m;
// Judge if the graph is a unicom plan.
bool visit[MAXVERTEXES + 1];
void floodFill(int now, int n);
bool isUnicom(int n);
//If a circle exists.
int in_node[MAXVERTEXES + 1];
vector myvec;
bool vv[MAXVERTEXES + 1];
void dfs(int now, int s);
int main()
{
freopen("input.in", "r", stdin);
freopen("output.out", "w", stdout);
int i, j;
int v1, v2;
double ans;
double tmp;
while( scanf("%d%d", &n, &m) != EOF )
{
/* init */
memset(cost, 0, sizeof(cost));
memset(canReach, false, sizeof(canReach));
memset(visit, false, sizeof(visit));
myvec.clear();
FORI(int, i, n)
{
cin >> nodes[i].x >> nodes[i].y;
// Set i`pre itself so that any arc entering i can replace this value.
nodes[i].pre = i;
}
FORI(int, j, m)
{
cin >> v1 >> v2;
v1--;
v2--;
if(v2 == 0)
continue;
canReach[v1][v2] = true;
cost[v1][v2] = sqrt( (double)( ( nodes[v1].x - nodes[v2].x ) * ( nodes[v1].x - nodes[v2].x ) +
( nodes[v1].y - nodes[v2].y ) * ( nodes[v1].y - nodes[v2].y ) ) );
if( cost[nodes[v2].pre][v2] == 0
|| cost[v1][v2] < cost[nodes[v2].pre][v2] )
nodes[v2].pre = v1;
}
// If this is not a unicom....
if( isUnicom(n) == false)
{
cout << "NO" << endl;
continue;
}
// Eliminate circles.
// Clear bool visit[],use again.
memset(visit, false, sizeof(visit));
FORI(int, i, n)
{
if( !visit[i] )
{
memset(vv, false, sizeof(vv));
dfs(i, i);
}
}
ans = 0;
FORI(int, i, n)
{
ans += cost[nodes[i].pre][i];
}
printf("%.2lf\n", ans);
}
return 0;
}
void floodFill(int now, int n)
{
visit[now] = true;
int i;
FORI(int, i, n)
{
if(canReach[now][i] == true && visit[i] == false)
floodFill(i, n);
}
}
bool isUnicom(int n)
{
int i;
// Let the flood fill...
floodFill(0, n);
FORI(int, i, n)
{
if( !visit[i] )
return false;
}
return true;
}
void dfs(int now, int s)
{
if(vv[now] && now == s)
{
vector::iterator it;
// in_node[i] records a arc outside the circle whose head is in_node[i] and the val is smallest.
int i;
int tmp;
int k;
int min_arc_in_circle_val = -1;
int min_entry_cost = INF;
int min_entry;
tmp = INF;
for(it=myvec.begin();it!=myvec.end();++it)
{
// Update min_arc_in_circle_val.
if( cost[nodes[(*it)].pre][(*it)] < tmp )
{
tmp = cost[nodes[(*it)].pre][(*it)];
min_arc_in_circle_val = tmp;
}
// Find in_node[i].
int tmp2 = INF;
//Set in_node[i] to i;
in_node[*it] = (*it);
FORI(int, i, n)
{
if ( !vv[i] && cost[i][*it] > 0 && cost[i][*it] < tmp2 )
{
in_node[*it] = i;
tmp2 = cost[i][*it];
}
}
}
// Find min_entry.
for(it=myvec.begin();it!=myvec.end();++it)
if( in_node[*it] != *it )
{
tmp = cost[in_node[*it]][*it] - ( cost[nodes[*it].pre][*it] - min_arc_in_circle_val );
if( tmp < min_entry_cost )
{
min_entry_cost = tmp;
min_entry = *it;
}
}
// Modify min_entry`s father to make a new entry.
nodes[min_entry].pre = in_node[min_entry];
return;
}
else
{
visit[now] = true;
vv[now] = true;
// If he has a father.
if( nodes[now].pre != now )
{
myvec.push_back(now);
dfs( nodes[now].pre, s);
myvec.pop_back();
}
}
}