题目大意:
求最小生成树的权值和,并输出。已经修建的路(已经连上的边)是不会算入到最后的ANS中。
Input
测试输入包含若干测试用例。每个测试用例的第1行给出村庄数目N ( 1< N < 100 );随后的 N(N-1)/2 行对应村庄间道路的成本及修建状态,每行给4个正整数,分别是两个村庄的编号(从1编号到N),此两村庄间道路的成本,以及修建状态:1表示已建,0表示未建。
当N为0时输入结束。
Sample Input
3
1 2 1 0
1 3 2 0
2 3 4 0
3
1 2 1 0
1 3 2 0
2 3 4 1
3
1 2 1 0
1 3 2 1
2 3 4 1
0
Sample Output
3
1
0
我的思路:就是把创建部分稍微做点修改,改成如果修建过,则此边的权值为0。
我出现的问题:我是初学PRIM,算法是自己根据定义写的,可能比较毛糙,问题不知道出在哪儿。提交上去是RE,(ACCESS_VIOLATION)。我仔细看过数组是否越界,我并没有看出有越界的地方。
上一道HDU1863畅通工程,同类型的题目我用这个算法AC了。
所以现在不知道错误在哪儿,请求各位指点一二。
下面是我的代码,运行没有问题,样例也通过。。。
#include "iostream"
#include "algorithm"
using namespace std;
typedef struct
{
int from;
int to;
int value; //权值
bool used; //是否被标记过
bool now; //是否为待选直接相邻边
}Edge;
Edge e[105];
bool V[105];//顶点集。
const int Inf=10000000;
bool Mycmp(Edge A,Edge B)
{
return A.value<B.value;
}
void Create(int n)
{
int i,length=0,Q;
for(i=0;i
V[i]=false;
for(i=0;i
e[i].used=false;
for(i=0;i
{
cin>>e[i].from>>e[i].to>>e[i].value>>Q;
if(Q==1)
e[i].value=0;
}
stable_sort(e,e+n,Mycmp);
}
void Find(int n,int from) //用来找出和这个顶点直接相连的边。
{
int i;
for(i=0;i<n;i++)
{
if(e[i].used==false&&(e[i].from==from||e[i].to==from))
{
if(V[e[i].from]==true&&V[e[i].to]==true) //用于判断是否会构成环
continue;
e[i].now=true;
}
}
}
void Clear(int n)
{
for(int i=0;i<n;i++)
e[i].now=false;
}
int Prim(int n,int m)
{
int i,from,to,j,jindex,value,min,ans=0;
from=e[0].from;
to=e[0].to;
e[0].used=true;
V[from]=true;
V[to]=true;
ans+=e[0].value;
for(i=1;i
{
Clear(n);
for(j=1;j
{
if(V[j]==true) //顺着顶点,把边挑选出来
{
Find(n,j);
}
}
min=Inf;
jindex=-1;
for(j=0;j
{
if(e[j].now==true)
{
if(min>e[j].now)
{
min=e[j].now;
jindex=j;
}
}
}
e[jindex].used=true; //找到合适的边
V[e[jindex].from]=true;
V[e[jindex].to]=true;
ans+=e[jindex].value;
}
return ans;
}
int main()
{
int n,m,ans,t,flag;
while(cin>>m)
{
if(m==0) //题意,如果为0则跳出
break;
n=m*(m-1)/2;
Create(n);
ans=Prim(n,m);
cout<<ans<<endl;
}
return 0;
}