LOJ10067 构造完全图

题目描述

对于完全图 ,若有且仅有一棵最小生成树为 ,则称完全图  是树  扩展出的。

给你一棵树 ,找出  能扩展出的边权和最小的完全图 

输入格式

第一行  表示树  的点数;

接下来  行三个整数 ;描述一条边()权值为 

保证输入数据构成一棵树。

输出格式

输出仅一个数,表示最小的完全图  的边权和。

样例

样例输入

4  
1 2 1  
1 3 1  
1 4 2  

样例输出

12

 

 题目给出的边是无序 双向边

若给出的是按树从上到下的边 且边值从小到大则prim可行

若给出的树从上到下的边值递增则prim可行 即保证每步prim选的d递增

WA 10分

 题目给出的边是双向边 无法判断哪个是父节点

输入文件(tree1.in) 

10
5 10 1
5 4 4
4 9 6
2 9 6
8 4 6
1 5 2
3 10 9
5 7 7
6 9 3

答案文件(tree1.out) 

319

5 4 4

8 4 6

就算保证x<y

1 5 2

5 4 4

还是会出现一个点的父节点存在两个

故需dfs建树

#include <bits/stdc++.h>
using namespace std;
const int N = 10000 + 5;
struct T {
    int p, d;
};
bool cmp(T x, T y) { return x.d < y.d; }
int vis[N];
T t[N];
int main() {
    int n, ans = 0;
    cin >> n;
    for (int i = 1; i < n; i++) {
        int x, y, z;
        cin >> x >> y >> z;//if (x>y){int t=x;x=y;y=t;} 还是不行
        ans += z;
        t[y].p = x;
        t[y].d = z;
    }
    sort(t + 1, t + n + 1, cmp);
    for (int i = 1; i <= n; i++) {
        vis[i] = 1;
        for (int j = 1; j <= n; j++) {
            if ((!vis[j]) && (t[j].p != i))
                ans += t[j].d + 1;
        }
    }
    cout << ans;
    return 0;
}

WA 10分

#include <bits/stdc++.h>
using namespace std;
const int N = 10000 + 5;
struct T {
    int id, p, d;  // id
};
bool cmp(T x, T y) { return x.d < y.d; }
int vis[N], e[N][N], n;
T t[N];
void dfs(int x) {  // pre prim
    vis[x] = 1;
    for (int i = 1; i <= n; i++) {
        if ((!vis[i]) && (e[x][i])) {
            t[i].p = x;
            t[i].d = e[x][i];
            t[i].id = i;
            dfs(i);
        }
    }
}
int main() {
    int ans = 0;
    cin >> n;
    for (int i = 1; i < n; i++) {
        int x, y, z;
        cin >> x >> y >> z;
        ans += z;
        e[x][y] = e[y][x] = z;
    }
    dfs(1);
    t[1].id = 1;
    sort(t + 1, t + n + 1, cmp);
    memset(vis, 0, sizeof(vis));
    for (int i = 1; i <= n; i++) {
        vis[t[i].id] = 1;  // vis[i]
        for (int j = 1; j <= n; j++) {
            if ((!vis[t[j].id]) && (t[j].p != t[i].id))
                ans += t[j].d + 1;  // vis[j] t[j].p!=i
        }
    }
    cout << ans;
    return 0;
}

WA 10分

#include<bits/stdc++.h>
using namespace std;
const int N=10000+5;
int vis[N],e[N][N],d[N],p[N],dd[N],n,ans=0;
void prim(){//pre prim
    d[1]=0;
    int k,min;
    for(int i=1;i<=n;i++){
        min=0x3f3f3f3f;
      for(int j=1;j<=n;j++)
       if((!vis[j])&&(min>d[j])){ min=d[j];k=j;
       }
       vis[k]=1;//漏了 
       //cout<<k<<endl;
       for(int j=1;j<=n;j++){
            if((!vis[j])&&(d[j]>e[k][j])) d[j]=e[k][j];
             else    if((!vis[j])) {
             ans+=dd[j]+1;
             cout<<dd[j]+1<<endl;
        }
       }
    }
}
void dfs(int x){
    vis[x]=1;
    for(int i=1;i<=n;i++){
        if((!vis[i])&&(e[x][i]!=0x3f3f3f3f)){//e[x][i]
            dd[i]=e[x][i];
            dfs(i);
        }
    }
}
int main(){
    cin>>n;
    memset(e,0x3f,sizeof(e));
    for(int i=1;i<n;i++){
        int x,y,z;
        cin>>x>>y>>z;
        ans+=z;
        e[x][y]=e[y][x]=z;
    }
    memset(d,0x3f,sizeof(d));
    dfs(1);
    memset(vis,0,sizeof(vis));
    prim();
    cout<<ans;
    return 0;
    } 

猜你喜欢

转载自www.cnblogs.com/wyh447154317/p/11665468.html