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\n",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\n",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\n",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\n",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.\n",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\n",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\n", 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\n",ans * 100);
    }
}
View Code

 

转载于:https://www.cnblogs.com/smallhester/p/10403095.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值