• kuangbin 最小生成树


    A & M - Jungle Roads HDU - 1301 

    题意:字母之间的路,求最小生成树

    题解:处理好建边以后就是一个Prime

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<sstream>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include <vector>
    #include <set>
    #include<queue>
    #include<map>
    using namespace std;
    
    #define ll long long
    #define llu unsigned long long
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    const int maxn =  50;
    const ll mod = 1e9+7;
    const double eps = 1e-8;
    
    bool vis[maxn];
    int lowc[maxn];
    
    int Prim(int cost[][maxn],int n)
    {
        int ans = 0;
        memset(vis,false,sizeof vis);
        vis[0] = true;
        for(int i=1;i<n;i++)
            lowc[i] = cost[0][i];
        for(int i=1;i<n;i++)
        {
            int minc = INF;
            int p = -1;
            for(int j=0;j<n;j++)
            {
                if(!vis[j] && minc > lowc[j])
                {
                    minc = lowc[j];
                    p = j;
                }
            }
            if(minc == INF)
                return -1;
            ans += minc;
            vis[p] = true;
            for(int j=0;j<n;j++)
                if(!vis[j] && lowc[j] > cost[p][j])
                    lowc[j] = cost[p][j];
        }
        return ans;
    }
    int main()
    {
        int n;
        while(scanf("%d",&n) && n)
        {
            int cost[maxn][maxn];
            for(int i=0;i<maxn;i++)
            {
                for(int j=0;j<maxn;j++)
                    if(i == j)
                        cost[i][j] = 0;
                    else
                        cost[i][j] = INF;
            }
            for(int i=1;i<n;i++)
            {
                char a;
                cin>>a;
                int num;
                cin>>num;
                for(int i=0;i<num;i++)
                {
                    char ch;
                    int len;
                    cin>>ch>>len;
                    cost[a-'A'][ch-'A'] = len;
                    cost[ch-'A'][a-'A'] = len;
                }
            }
    
            int ans = Prim(cost,n);
            cout<<ans<<endl;
        }
    
    }
    View Code

    B - Networking POJ - 1287 

    题意:有重复边的跑最小生成树

    题解:边取小跑Prime

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<sstream>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include <vector>
    #include <set>
    #include<queue>
    
    using namespace std;
    
    #define ll long long
    #define llu unsigned long long
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    const int maxn = 1e2+5;
    bool vis[maxn];
    int lowc[maxn];
    int Prim(int cost[][maxn],int n)
    {
        int ans = 0;
        memset(vis,false,sizeof vis);
        vis[1] = true;
        for(int i=2;i<=n;i++)
            lowc[i] = cost[1][i];
        for(int i=2;i<=n;i++)
        {
            int minc = INF;
            int p = -1;
            for(int j=1;j<=n;j++)
                if(!vis[j] && minc > lowc[j])
                {
                    minc = lowc[j];
                    p = j;
                }
            if(minc == INF)
                return -1;
            ans += minc;
            vis[p] = true;
            for(int j=1;j<=n;j++)
                if(!vis[j] && lowc[j] > cost[p][j])
                    lowc[j] = cost[p][j];
        }
        return ans;
    
    }
    int main()
    {
        int n,m;
        while(scanf("%d",&n) && n)
        {
            scanf("%d",&m);
            int cost[maxn][maxn];
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(i == j)
                        cost[i][j] = 0;
                    else
                        cost[i][j] = INF;
            for(int i=0;i<m;i++)
            {
                int a,b,c;
                scanf("%d%d%d",&a,&b,&c);
                cost[a][b] = min(cost[a][b],c);
                cost[b][a] = min(cost[b][a],c);
                cost[a][b] = cost[b][a] = min(cost[a][b],cost[b][a]);
            }
            int ans = Prim(cost,n);
            printf("%d
    ",ans);
        }
    }
    View Code

    C - Building a Space Station POJ - 2031

    题意:三维上的球上建最小生成树

    题解:处理边即可

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<sstream>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include <vector>
    #include <set>
    #include<queue>
    
    using namespace std;
    
    #define ll long long
    #define llu unsigned long long
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    const int maxn = 1e2+5;
    
    struct node
    {
        double x,y,z,r;
    }a[maxn];
    double dis(double x1,double y1,double z1,double r1,double x2,double y2,double z2,double r2)
    {
        double len = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2);
        double ans = sqrt(len) - r1 - r2;
        return max(0.0,ans);
    }
    bool vis[maxn];
    double lowc[maxn];
    double Prime(double cost[][maxn],int n)
    {
        double ans = 0;
        memset(vis,0,sizeof vis);
        vis[0] = true;
        for(int i=1;i<n;i++)
            lowc[i] = cost[0][i];
        for(int i=1;i<n;i++)
        {
            double minc = 9999999999.9;
            int p = -1;
            for(int j=0;j<n;j++)
                if(!vis[j] && minc > lowc[j])
                {
                    p = j;
                    minc = lowc[j];
                }
            ans += minc;
            vis[p] = true;
            for(int j=0;j<n;j++)
                if(!vis[j] && lowc[j] > cost[p][j])
                    lowc[j] = cost[p][j];
        }
        return ans;
    }
    int main()
    {
        int n;
        while(scanf("%d",&n) && n)
        {
            double cost[maxn][maxn];
            for(int i=0;i<n;i++)
                scanf("%lf %lf %lf %lf",&a[i].x,&a[i].y,&a[i].z,&a[i].r);
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++)
                    cost[i][j] = dis(a[i].x,a[i].y,a[i].z,a[i].r,a[j].x,a[j].y,a[j].z,a[j].r);
            double ans = Prime(cost,n);
            printf("%.3f
    ",ans);
        }
    }
    View Code

    D - Constructing Roads POJ - 2421 

    题意:邻接矩阵有些边权值为0,求最小生成树

    题解:Prim

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<sstream>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include <vector>
    #include <set>
    #include<queue>
    
    using namespace std;
    
    #define ll long long
    #define llu unsigned long long
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    const int maxn = 1e2+5;
    
    int vis[maxn];
    int lowc[maxn];
    int cost[maxn][maxn];
    
    int Prim(int cost[][maxn],int n)
    {
        int ans = 0;
        memset(vis,0,sizeof vis);
        vis[1] = true;
        for(int i=2;i<=n;i++)
            lowc[i] = cost[1][i];
        for(int i=2;i<=n;i++)
        {
            int minc = INF;
            int p = -1;
            for(int j=1;j<=n;j++)
                if(!vis[j] && minc > lowc[j])
                {
                    minc = lowc[j];
                    p = j;
                }
            ans += minc;
            vis[p] = true;
            for(int j=1;j<=n;j++)
                if(!vis[j] && lowc[j] > cost[p][j])
                    lowc[j] = cost[p][j];
        }
        return ans;
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&cost[i][j]);
        int q;
        scanf("%d",&q);
        for(int i=0;i<q;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            cost[a][b] = cost[b][a] = 0;
        }
        int ans = Prim(cost,n);
        printf("%d
    ",ans);
    }
    View Code

     E - QS Network ZOJ - 1586 

    题意:最小生出树,边的值还需要加上两个顶点的值

    题解:只需要将顶点的值加到其权值上即可

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<sstream>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include <vector>
    #include <set>
    #include<queue>
    
    using namespace std;
    
    #define ll long long
    #define llu unsigned long long
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    const int maxn = 1e3+5;
    
    bool vis[maxn];
    int lowc[maxn];
    int cost[maxn][maxn];
    int a[maxn];
    int prim(int cost[][maxn],int n)
    {
        int ans = 0 ;
        memset(vis,false,sizeof vis);
        vis[1] = true;
        for(int i=2;i<=n;i++)
            lowc[i] = cost[1][i];
        for(int i=2;i<=n;i++)
        {
            int minc = INF;
            int p = -1;
            for(int j=1;j<=n;j++)
            {
                if(!vis[j] && minc > lowc[j])
                {
                    minc = lowc[j];
                    p = j;
                }
            }
            ans += minc;
            vis[p] = true;
            for(int j=1;j<=n;j++)
                if(!vis[j] && lowc[j] > cost[p][j])
                    lowc[j] = cost[p][j];
        }
        return ans;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            int ans = 0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++) {
                    scanf("%d", &cost[i][j]);
                    cost[i][j] += a[i] + a[j];
                }
            ans += prim(cost,n);
            printf("%d
    ",ans);
        }
    }
    View Code

    F - Truck History POJ - 1789 

    题意:两个字符串之间不同的个数为边的权值,跑最小生成树

    题解:处理边之后跑最小生成树

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<sstream>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include <vector>
    #include <set>
    #include<queue>
    
    using namespace std;
    
    #define ll long long
    #define llu unsigned long long
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    const int maxn = 2e3+5;
    
    bool vis[maxn];
    int lowc[maxn];
    int cost[maxn][maxn];
    int a[maxn];
    int prim(int cost[][maxn],int n)
    {
        int ans = 0 ;
        memset(vis,false,sizeof vis);
        vis[1] = true;
        for(int i=2;i<=n;i++)
            lowc[i] = cost[1][i];
        for(int i=2;i<=n;i++)
        {
            int minc = INF;
            int p = -1;
            for(int j=1;j<=n;j++)
            {
                if(!vis[j] && minc > lowc[j])
                {
                    minc = lowc[j];
                    p = j;
                }
            }
            ans += minc;
            vis[p] = true;
            for(int j=1;j<=n;j++)
                if(!vis[j] && lowc[j] > cost[p][j])
                    lowc[j] = cost[p][j];
        }
        return ans;
    }
    int main()
    {
        int n;
        while(scanf("%d",&n) && n)
        {
            char str[maxn][10];
            for(int i=1;i<=n;i++)
                scanf("%s",str[i]);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                {
                    int tmp = 0;
                    for(int k=0;k<7;k++)
                        if(str[i][k] != str[j][k])
                            tmp++;
                    cost[i][j]  = cost[j][i] = tmp;
                }
            int ans  = prim(cost,n);
            printf("The highest possible quality is 1/%d.
    ",ans);
        }
    }
    View Code

     J - Borg Maze POJ - 3026 

    题意:迷宫之中的MST

    题解:先bfs预处理,之后在进行MST,输入的时候有坑点,wa了好几次

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<sstream>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include <vector>
    #include <set>
    #include<queue>
    
    using namespace std;
    
    #define ll long long
    #define llu unsigned long long
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    const int maxn = 550;
    int tree[maxn][maxn],id[maxn][maxn],dis[maxn][maxn],n,m,tot;
    bool vis[maxn][maxn];
    int lowc[maxn],visit[maxn];
    char mp[maxn][maxn];
    int dx[] = {0,1,0,-1};
    int dy[] = {1,0,-1,0};
    struct node
    {
        int x,y;
    };
    bool check(int x,int y)
    {
        if(x >= 1 && x <= n && y >= 1 && y <= m && !vis[x][y] && mp[x][y] != '#')
            return true;
        return false;
    }
    void bfs(int x,int y)
    {
        memset(vis,false,sizeof vis);
        memset(dis,0,sizeof dis);
        queue<node>que;
        node temp;
        temp.x = x;
        temp.y = y;
        que.push(temp);
        vis[x][y] = true;
        while(!que.empty())
        {
            temp = que.front();
            que.pop();
            for(int i=0;i<4;i++)
            {
                int nx = temp.x + dx[i];
                int ny = temp.y + dy[i];
                if(check(nx,ny))
                {
                    vis[nx][ny] = true;
                    dis[nx][ny] = dis[temp.x][temp.y] + 1;
                    if(mp[nx][ny] == 'A' || mp[nx][ny] == 'S')
                        tree[id[x][y]][id[nx][ny]] = tree[id[nx][ny]][id[x][y]] = dis[nx][ny];
                    que.push(node{nx,ny});
                }
            }
        }
    }
    
    int Prime(int cost[][maxn],int n)
    {
        int ans = 0;
        memset(visit,false,sizeof visit);
        visit[1] = true;
        for(int i=2;i<=n;i++)
            lowc[i] = cost[1][i];
        for(int i=2;i<=n;i++)
        {
            int minc = INF;
            int p = -1;
            for(int j=1;j<=n;j++)
                if(!visit[j] && minc > lowc[j])
                {
                    minc = lowc[j];
                    p = j;
                }
            ans += minc;
            visit[p] = true;
            for(int j=1;j<=n;j++)
                if(!visit[j] && lowc[j] > cost[p][j])
                    lowc[j] = cost[p][j];
        }
        return ans;
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int tot = 0;
            scanf("%d%d ",&m,&n);
            for(int i=1;i<=n;i++)
                gets(mp[i] + 1);
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(mp[i][j] == 'A' || mp[i][j] == 'S')
                        id[i][j] = ++tot;
            for(int i=1;i<=tot;i++)
                for(int j=1;j<=tot;j++)
                    if(i == j)
                        tree[i][j] = 0;
                    else
                        tree[i][j] = INF;
            for(int i=1;i<=n;i++)
                for(int j=1;j<=n;j++)
                    if(mp[i][j] == 'A' || mp[i][j] == 'S')
                        bfs(i,j);
            int ans = Prime(tree,tot);
            printf("%d
    ",ans);
        }
    }
    View Code

    L - 还是畅通工程 HDU - 1233 

    题意:直接就是求最小生成树了

    题解:板子

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<sstream>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include <vector>
    #include <set>
    #include<queue>
    #include<map>
    using namespace std;
    
    #define ll long long
    #define llu unsigned long long
    #define INF 0x3f3f3f3f
    #define PI acos(-1.0)
    const int maxn =  1005;
    const ll mod = 1e9+7;
    const double eps = 1e-8;
    
    int lowc[maxn];
    bool vis[maxn];
    
    int Prime(int cost[][maxn],int n)
    {
        int ans = 0;
        memset(vis,false,sizeof vis);
        vis[0] = true;
        for(int i=1;i<n;i++)
            lowc[i] = cost[0][i];
        for(int i=1;i<n;i++)
        {
            int minc = INF;
            int p = -1;
            for(int j=0;j<n;j++)
            {
                if(!vis[j] && minc > lowc[j])
                {
                    minc = lowc[j];
                    p = j;
                }
            }
            if(minc == INF)
                return -1;
            ans += minc;
            vis[p] = true;
            for(int j=0;j<n;j++)
                if(!vis[j] && lowc[j] > cost[p][j])
                    lowc[j] = cost[p][j];
        }
        return ans;
    }
    int main()
    {
            int n;
            while(scanf("%d",&n) && n)
            {
                int cost[maxn][maxn];
                memset(cost,0,sizeof cost);
                for (int i = 0; i < n * (n - 1) / 2; i++)
                {
                    int a, b, l;
                    scanf("%d%d%d", &a, &b, &l);
                    cost[a-1][b-1] = l;
                    cost[b-1][a-1] = l;
                }
    
                int ans = Prime(cost, n);
                printf("%d
    ", ans);
            }
    }
    View Code

    N - 畅通工程再续 HDU - 1875 

    题意:岛之间造桥,只有长度在10~1000才可以造,问最少的花费,花费是桥的长度*100

    题解:INF值的判定,INF是长度小于10或者长度大于1000,其余就是Prime的板子

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<sstream>
    #include<cmath>
    #include<stack>
    #include<cstdlib>
    #include <vector>
    #include <set>
    #include<queue>
    #include<map>
    using namespace std;
    
    #define ll long long
    #define llu unsigned long long
    #define INF 99999999999.9
    #define PI acos(-1.0)
    const int maxn =  1005;
    const ll mod = 1e9+7;
    const double eps = 1e-8;
    
    double lowc[maxn];
    bool vis[maxn];
    double dis(int x1,int y1,int x2,int y2)
    {
        double ans = sqrt((double)(x2-x1)*(x2-x1)*1.0 + (y2-y1)*(y2-y1)*1.0);
        //cout<<ans<<endl;
        return ans;
    }
    bool check(double x)
    {
        //cout<<x<<endl;
        if(x>=10.0 && x<=1000.0)
            return true;
        else
            return false;
    }
    double Prime(double cost[][maxn],int n)
    {
        double ans = 0;
        memset(vis,false,sizeof vis);
        vis[0] = true;
        for(int i=1;i<n;i++)
            lowc[i] = cost[0][i];
        for(int i=1;i<n;i++)
        {
            double minc = INF;
            int p = -1;
            for(int j=0;j<n;j++)
            {
                if(!vis[j] && minc > lowc[j])
                {
                    minc = lowc[j];
                    p = j;
                }
            }
            if(minc == INF)
                return -1;
            ans += minc;
            vis[p] = true;
            for(int j=0;j<n;j++)
                if(!vis[j] && lowc[j] > cost[p][j])
                    lowc[j] = cost[p][j];
        }
        return ans;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            int n;
            scanf("%d",&n);
            int x[maxn];
            int y[maxn];
            double cost[maxn][maxn];
            for(int i=0;i<n;i++)
                scanf("%d %d",&x[i],&y[i]);
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<n;j++)
                {
                    if(i == j) {
                        cost[i][j] = 0;
                        continue;
                    }
                    else if(check(dis(x[i],y[i],x[j],y[j]))) {
                        //cout<<dis(x[i], y[i], x[j], y[j])<<endl;
                        cost[i][j] = dis(x[i], y[i], x[j], y[j]);
                        cost[j][i] = dis(x[i], y[i], x[j], y[j]);
                    }
                    else if(!check(dis(x[i],y[i],x[j],y[j])))
                        cost[i][j] = INF;
                }
            }
    
            //cout<<cost[0][1]<<endl;
            double ans = Prime(cost,n);
            if(ans == -1)
                puts("oh!");
            else
                printf("%.1f
    ",ans * 100);
        }
    }
    View Code
  • 相关阅读:
    安卓表格布局android:collapseColumns,android:shrinkColumns和stretchColumn
    Cocos2dx 学习记录 [2] 关于混合和高亮一些知识点的体会
    01背包问题
    textarea文本域宽度和高度(width、height)自己主动适应变化处理
    SSL协议具体解释
    Geeks Union-Find Algorithm Union By Rank and Path Compression 图环算法
    Linux内核源代码分析方法
    linux服务之svn
    java实现第七届蓝桥杯冰雹数
    java实现第七届蓝桥杯冰雹数
  • 原文地址:https://www.cnblogs.com/smallhester/p/10403095.html
Copyright © 2020-2023  润新知