zoukankan      html  css  js  c++  java
  • uva 1151

    最小生成树算法简单

    只是增加了一些新的东西,对于需要最小生成树算法 和中 并检查使用的一系列 还有一些更深入的了解。

    方法的一些复杂问题

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int maxn = 1005;
    
    struct point
    {
        int x;
        int y;
    }pp[maxn];
    struct edge
    {
        int s;
        int e;
        int dist;
    }l[maxn*maxn];
    int n,q,m;
    int p[maxn];
    vector<int> g[10];
    int c[10];
    int distance_(point a,point b)
    {
        return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
    }
    int cmp(edge a,edge b)
    {
        return a.dist < b.dist;
    }
    int find_(int x)
    {
        return p[x]==x?x:p[x]=find_(p[x]);
    }
    bool merge_(int a,int b)
    {
        int x=find_(a);
        int y=find_(b);
        if(x==y) return false;
        p[x]=y;
        return true;
    }
    int kruskal()
    {
        int ans=0;
        int num=0;
        for(int i=0;i<m&&num<n-1;i++)
        {
            if(merge_(l[i].s,l[i].e))
            {
                num++;
                ans+=l[i].dist;
            }
        }
        return ans;
    }
    void solve()
    {
        for(int i=0;i<=n;i++) p[i]=i;
        int ans = kruskal();
        for(int s=1;s<(1<<q);s++)
        {
            int cost=0;
            for(int tt=0;tt<=n;tt++) p[tt]=tt;
            for(int j=0;j<q;j++)
            {
                if(!((s>>j)&1)) continue;
                cost+=c[j];
                for(int k=0;k<g[j].size();k++)
                {
                    merge_(g[j][k],g[j][0]);
                }
            }
            ans=min(ans,cost+kruskal());
        }
        printf("%d
    ",ans);
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&q);
            for(int i=0;i<10;i++) g[i].clear();
            for(int i=0;i<q;i++)
            {
                int cnt;
                scanf("%d%d",&cnt,&c[i]);
                int a;
                for(int j=0;j<cnt;j++)
                {
                    scanf("%d",&a);
                    g[i].push_back(a);
                }
            }
            for(int i=1;i<=n;i++)
            {
                scanf("%d%d",&pp[i].x,&pp[i].y);
            }
            m=0;
            for(int i=1;i<=n;i++)
            {
                for(int j=i+1;j<=n;j++)
                {
                    l[m].s=i;
                    l[m].e=j;
                    l[m++].dist=distance_(pp[i],pp[j]);
                }
            }
            sort(l,l+m,cmp);
            solve();
            if(t) printf("
    ");
        }
        return 0;
    }
    

    鉴于需要使用几个选项 枚举子 算法。

    在上面的解决方法。它使用的二进制计数的方法的帮助的一个子集。枚举算法的子集只适用于相对小的一组元素的。

    采取结构上述表示的方法edge该方法,与其说开放数组。我觉得跟结构可以更可读的代码。


  • 相关阅读:
    正则表达式 常用的通配符
    自己做的前端试题总结
    【总结】IE和Firefox的Javascript兼容性总结
    对GCD的一些理解和实践
    兼容iOS 10 资料整理笔记
    iOS开发 适配iOS10以及Xcode8
    颜色控制
    UISegmentedControl 分段控件
    Target—Action
    UITouch 点击事件
  • 原文地址:https://www.cnblogs.com/lcchuguo/p/4589053.html
Copyright © 2011-2022 走看看