问题描述
- ACM HDU1879继续畅通工程 提交RE.求各路大神帮忙看一下哪儿错了
-
题目大意:
求最小生成树的权值和,并输出。已经修建的路(已经连上的边)是不会算入到最后的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
0Sample 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;
}
解决方案
算法有问题
/*
hdu1879
2013-03-18 15:25:50 Accepted 1879 406MS 360K 1188 B
典型的最小生成树,在做并查集时做的这道题,
所以使用并查集实现的克鲁斯卡尔算法
*/
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
struct node {
int start ,end,expense,flag;
}data[5005];
int father[105];
void make_set(int n)
{
for(int i=1;i<=n;i++)
father[i]=i;
}
int find_set(int x)
{
if(x^father[x])
father[x]=find_set(father[x]);
return father[x];
}
int union_set(int x,int y)
{
x=find_set(x);
y=find_set(y);
if(x==y)
return 0;
father[x]=y;
return 1;
}
bool cmp(node a,node b)
{
return a.expense<b.expense;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
if(!n)
break;
make_set(n);
int ans=0;
int m=(n-1)*n/2;
for(int i=0;i<m;i++)
{
scanf("%d%d%d%d",&data[i].start,&data[i].end,&data[i].expense,&data[i].flag);
if(data[i].flag)//当道路修通时,规定一节点为另一节点的父亲
father[data[i].start]=data[i].end;
}
sort(data,data+m,cmp);//按道路的花费升序排列
//在不构成环的前提下,选择最短的边,有贪心的思想
for(int i=0;i<m;i++)
{
if(union_set(data[i].start,data[i].end))
ans+=data[i].expense;
}
printf("%dn",ans);
}
return 0;
}