题解

128 条题解

  • 0
    @ 2006-10-05 08:48:37

    标准的kruskal

  • 0
    @ 2006-10-04 22:01:18

    编译通过...

    ├ 测试数据 01:答案正确... 0ms

    ├ 测试数据 02:答案正确... 0ms

    ├ 测试数据 03:答案正确... 0ms

    ├ 测试数据 04:答案正确... 0ms

    ├ 测试数据 05:答案正确... 0ms

    ├ 测试数据 06:答案正确... 0ms

    ├ 测试数据 07:答案正确... 0ms

    ├ 测试数据 08:答案正确... 0ms

    ├ 测试数据 09:答案正确... 0ms

    ├ 测试数据 10:答案正确... 0ms

    ---|---|---|---|---|---|---|---|-

    Accepted 有效得分:100 有效耗时:0ms

  • 0
    @ 2006-10-03 23:41:59

    贪心+并查集

    从花费小的到大的依次合并。每一次合并不一定能够减少一个堆数。如果两个节点本来已经在一堆,那么这个合并就是不必要的。

  • 0
    @ 2006-10-03 21:10:24

    Kruskal,合并n-k次而非标准的n-1次

  • 0
    @ 2006-10-03 19:58:59

    [转化]最小生成森林问题(k颗树)。

    [算法]我们用贪心+并查集的经典算法,稍加改进,在判边的时候记录已经合并过多少次集合,合并了n-k次以后即得到解。O(mlogm)。

    若对该算法不了解,可参考最小生成树的相关资料。

  • -1
    @ 2016-09-17 17:11:37

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    struct node{
    int x,y,z;
    }gg[20005];
    int fa[20005],cnt;
    int find(int x)
    {
    if(x!=fa[x])return fa[x]=find(fa[x]);
    return x;
    }
    int unionn(int x,int y)
    {
    int a=find(x),b=find(y);
    fa[a]=b;
    cnt++;
    }
    int cmp(const node &a,const node &b)
    {
    return a.z<b.z;
    }
    int main()
    {
    int n,m,k,ans=0;
    cin>>n>>m>>k;
    if(n==k)
    {
    cout<<"0";
    return 0;
    }
    for(int i=1;i<=n;i++)
    fa[i]=i;
    for(int i=1;i<=m;i++)
    cin>>gg[i].x>>gg[i].y>>gg[i].z;
    sort(gg+1,1+gg+m,cmp);
    for(int i=1;i<=m;i++)
    {
    if(cnt==n-k)break;
    if(find(gg[i].x)!=find(gg[i].y))
    {
    unionn(gg[i].x,gg[i].y);
    ans+=gg[i].z;
    }
    }
    if(n-cnt!=k)
    {
    cout<<"No Answer";
    return 0;
    }
    printf("%d",ans);
    }

  • -1
    @ 2016-09-02 21:42:21

    #include <cstdio>
    #include <algorithm>

    struct NODE{
    int s1,s2,val;
    }a[20000];

    bool cmp(NODE a,NODE b){
    return a.val<b.val;
    }

    int pre[20000];
    int find(int x){
    if(x!=pre[x])
    pre[x]=find(pre[x]);
    return pre[x];
    }

    int main(){
    int n,m,k,sum=0,count=0;
    freopen("in.txt","r",stdin);
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
    pre[i]=i;
    for(int i=0;i<m;i++){
    int s1,s2,val;
    scanf("%d%d%d",&s1,&s2,&val);
    a[i].s1=s1,a[i].s2=s2,a[i].val=val;
    }
    std::sort(a,a+m,cmp);
    for(int i=0;i<m;i++){
    if(count==n-k)
    break;
    int f1=find(a[i].s1);
    int f2=find(a[i].s2);
    if(f1==f2)
    continue;
    pre[f1]=f2;
    sum+=a[i].val;
    count++;
    }
    if(n-count!=k)
    printf("No Answer");
    else
    printf("%d",sum);
    return 0;
    }

  • -1
    @ 2016-08-14 21:27:02
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    int f[1005];
    struct edge
    {
        int from,to,len;
    }road[80005];
    bool comp(edge a,edge b){
        return a.len<b.len;
    }
    int getf(int x)
    {
        return f[x]==x?x:f[x]=getf(f[x]);
    }
    int main()
    {
        int n,m,k;
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1;i<=m;i++)
            scanf("%d%d%d",&road[i].from,&road[i].to,&road[i].len);
        sort(road+1,road+m+1,comp);
        int ans=0,j=n;
        for(int i=1;i<=n;i++) f[i]=i;
        for(int i=1;i<=m && j>k;i++) {
            int p1=getf(road[i].from);
            int p2=getf(road[i].to);
            if(p1!=p2) {
                ans+=road[i].len;
                f[p1]=p2;
                j--;
            }
        }
        j==k?printf("%d",ans):puts("No Answer");
        return 0;
    }
    

    kruskal模板水过,记得数组开大点

信息

ID
1234
难度
5
分类
树结构 | 生成树 点击显示
标签
递交数
3664
已通过
1131
通过率
31%
被复制
8
上传者