版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wlh1998/article/details/76026515
#include<stdio.h>
#include<string.h>
const int INF = 0x3f3f3f3f;
const int maxn = 1e3;
int fa[maxn];
int mp[maxn][maxn]; // 存图;
int vis[maxn]; //是否在新图内;
int dis[maxn]; //第i个顶点到新图最短距离;
int prim(int n);
int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
int main (){
int m;
int cun1,cun2,cost,ans = 0,flag;
while (scanf("%d", & m) != EOF && m != 0){
memset(mp,0x3f,sizeof(mp));
memset(vis,0,sizeof(vis));
for (int i = 0; i < maxn; i++){
fa[i] = i;
}
for (int i = 0; i < m * (m-1) / 2; i++){
scanf("%d%d%d%d", &cun1,&cun2,&cost, &flag);
cun1--;
cun2--;
mp[cun1][cun2] = cost;
mp[cun2][cun1] = cost;
if (flag == 1){
fa[find(cun2)] = find(cun1);
mp[cun1][cun2] = 0;
mp[cun2][cun1] = 0;
}
}
ans = prim(m);
printf("%d\n",ans);
}
}
int prim(int n){
int ans = 0;
int m = 0;
for (int i = 0; i < n; i++){
if(find(i) == i) {
m++;
}
}
for (int i = 0; i < n; i++) dis[i] = mp[0][i];
for (int i = 0; i < n; i++){
if (find(i) == find(0)){
vis[i] = 1;
dis[i] = 0;
}
}
for (int i = 1; i < n; i++){
if (vis[i]){
for (int j = 0; j < n; j++) {
if (!vis[j] && mp[i][j] < dis[j]){
dis[j] = mp[i][j];
}
}
}
}
for (int i = 1; i < n; i++){
int minn = INF; // 旧图到新图最短距离
int pos = -1; // 旧图最近点标号;
for (int j = 0; j < n; j++){
if(!vis[j] && minn > dis[j]) {
minn = dis[j];
pos = j;
}
}
if (minn == INF) return ans;
ans += minn; //更新答案;
vis[pos] = 1;
for (int j = 0; j < n; j++){
if (find(j) == find(pos)){
vis[j] = 1;
dis[j] = 0;
}
}
for (int i = 1; i < n; i++){
if (vis[i]){
for (int j = 0; j < n; j++) {
if (!vis[j] && mp[i][j] < dis[j]){
dis[j] = mp[i][j];
}
}
}
}
}
return ans;
}
前一个写的很复杂,各种合并出错,每次更新需遍历整个图,最初这wa了几发
//畅通工程修过直接cost为零过
//并不知道之前哪错了。。。。。。
#include<stdio.h>
#include<string.h>
const int INF = 0x3f3f3f3f;
const int maxn = 1e3;
int fa[maxn];
int mp[maxn][maxn]; // 存图;
int vis[maxn]; //是否在新图内;
int dis[maxn]; //第i个顶点到新图最短距离;
int prim(int n);
int find(int x){
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
int main (){
int m;
int cun1,cun2,cost,ans = 0,flag;
while (scanf("%d", & m) != EOF && m != 0){
memset(mp,0x3f,sizeof(mp));
memset(vis,0,sizeof(vis));
for (int i = 0; i < maxn; i++){
fa[i] = i;
}
for (int i = 0; i < m * (m-1) / 2; i++){
scanf("%d%d%d%d", &cun1,&cun2,&cost, &flag);
cun1--;
cun2--;
mp[cun1][cun2] = cost;
mp[cun2][cun1] = cost;
if (flag == 1){
mp[cun1][cun2] = 0;
mp[cun2][cun1] = 0;
}
}
ans = prim(m);
printf("%d\n",ans);
}
}
int prim(int n){
int ans = 0;
memset(vis,0,sizeof(vis));
vis[0] = 1; //注意第一个点的初始化;
for (int i = 0; i < n; i++) dis[i] = mp[0][i]; // 新图第一个点为0,初始化dis;
for (int i = 1; i < n; i++){ // 加入第i+1个点
int minn = INF; // 旧图到新图最短距离
int pos = -1; // 旧图最近点标号;
for (int j = 0; j < n; j++){
if(!vis[j] && minn > dis[j]) {
minn = dis[j];
pos = j;
}
}
if (minn == INF) return -1;
ans += minn; //更新答案;
vis[pos] = 1;
for (int j = 0; j < n; j++) {
if (!vis[j] && mp[pos][j] < dis[j]){
dis[j] = mp[pos][j];
}
}
}
return ans;
}