码迷,mamicode.com
首页 > 其他好文 > 详细

裸地最小生成树

时间:2018-02-25 20:33:25      阅读:288      评论:0      收藏:0      [点我收藏+]

标签:blog   cto   个数   size   ace   namespace   最优   ack   push   

【例4-9】城市公交网建设问题

链接:http://ybt.ssoier.cn:8088/problem_show.php?pid=1348
时间限制: 1000 ms         内存限制: 65536 KB

【题目描述】

有一张城市地图,图中的顶点为城市,无向边代表两个城市间的连通关系,边上的权为在这两个城市之间修建高速公路的造价,研究后发现,这个地图有一个特点,即任一对城市都是连通的。现在的问题是,要修建若干高速公路把所有城市联系起来,问如何设计可使得工程的总造价最少?

【输入】

n(城市数,1<≤n≤100)

e(边数)

以下e行,每行3个数i,j,wiji,j,wij,表示在城市i,j之间修建高速公路的造价。

【输出】

n-1行,每行为两个城市的序号,表明这两个城市间建一条高速公路。

【输入样例】

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

【输出样例】

1  2
2  3
3  4
3  5
#include<bits/stdc++.h>
using namespace std;
const int maxM = 10005, maxN = 105;
struct edge{
    int u,v,w;
};
int f[maxN];
edge G[maxM];
struct node{
    int u,v;
    bool operator <(const node A)const{
        if(A.u == u)return A.v < v;
        return A.u < u;
    }
}; 
priority_queue <node>Q;
int Find(int x){
    if(f[x]==x)return x;
    else return f[x]=Find(f[x]);
}
bool Same(int x,int y){
    return Find(x)==Find(y);
}
void Unionset(int x,int y){
    int u=Find(x),v=Find(y);
    if(u==v)return;
    else f[u]=v;
}
bool cmp(edge x,edge y){
    return x.w<y.w;
}
int main(){
    int n,k,tot=0,t=0,ans=0;
    cin>>n>>k;
    for(int i=1;i<=k;i++)
        scanf("%d%d%d",&G[i].u,&G[i].v,&G[i].w);
    for(int i=1;i<=n;i++)f[i]=i;
    sort(G+1,G+1+k,cmp);
    for(int i=1;i<=k;i++){
        if(t==n-1)break;
        if(!Same(G[i].u,G[i].v)){
            Unionset(G[i].u,G[i].v);
            Q.push((node){min(G[i].u,G[i].v),max(G[i].u,G[i].v)});
            t++;
        }
    }
    while(!Q.empty()){
        node p = Q.top();
        Q.pop();
        cout<<p.u<<" "<<p.v<<endl;
    }
}

【例4-10】最优布线问题

时间限制: 1000 ms         内存限制: 65536 KB

【题目描述】

学校有n台计算机,为了方便数据传输,现要将它们用数据线连接起来。两台计算机被连接是指它们有数据线连接。由于计算机所处的位置不同,因此不同的两台计算机的连接费用往往是不同的。

当然,如果将任意两台计算机都用数据线连接,费用将是相当庞大的。为了节省费用,我们采用数据的间接传输手段,即一台计算机可以间接的通过若干台计算机(作为中转)来实现与另一台计算机的连接。

现在由你负责连接这些计算机,任务是使任意两台计算机都连通(不管是直接的或间接的)。

【输入】

第一行为整数n(2≤n≤100),表示计算机的数目。此后的n行,每行n个整数。第x+1行y列的整数表示直接连接第x台计算机和第y台计算机的费用。

【输出】

一个整数,表示最小的连接费用。

【输入样例】

3
0 1 2
1 0 1
2 1 0

【输出样例】

2

【提示】

注:表示连接1和2,2和3,费用为2。

#include<bits/stdc++.h>
using namespace std;
#define maxn 105
#define INF 10000008
struct edge{
    int to,co;
};
vector <edge> G[maxn];
int minx[maxn];
bool vis[maxn];
int main(){
    int N, MST = 0;
    cin>>N;
    for(int i = 1; i <= N; i++)
        for(int j = 1; j <= N; j++){
            int w;
            cin>>w;
            if(w)G[i].push_back((edge){j,w});
        }
    memset(minx,0x7f,sizeof(minx));
    minx[1] = 0;
    for(int i = 1; i <= N; i++){
        int minn = INF, k = 0;
        for(int j = 1; j <= N; j++){        
            if(minx[j] < minn && !vis[j])
                minn = minx[j], k = j;
        }
        vis[k] = 1;
        MST += minx[k];
        for(int m = 0; m < G[k].size(); m++){
            edge v = G[k][m];
            if(!vis[v.to] && minx[v.to] > v.co)
                minx[v.to] = v.co;
        }
                
    }
    cout<<MST<<endl;
}

局域网(net)

时间限制: 1000 ms         内存限制: 65536 KB

【题目描述】

某个局域网内有n(n≤100)台计算机,由于搭建局域网时工作人员的疏忽,现在局域网内的连接形成了回路,我们知道如果局域网形成回路那么数据将不停的在回路内传输,造成网络卡的现象。因为连接计算机的网线本身不同,所以有一些连线不是很畅通,我们用f(i,j)表示i,j之间连接的畅通程度(f(i,j)≤1000),f(i,j)值越小表示i,j之间连接越通畅,f(i,j)为0表示i,j之间无网线连接。现在我们需要解决回路问题,我们将除去一些连线,使得网络中没有回路,并且被除去网线的Σf(i,j)最大,请求出这个最大值。

【输入】

第一行两个正整数n k

接下来的k行每行三个正整数i j m表示i,j两台计算机之间有网线联通,通畅程度为m。

【输出】

一个正整数,Σf(i,j)的最大值。

【输入样例】

5 5
1 2 8
1 3 1
1 5 3
2 4 5
3 4 2

【输出样例】

8
#include<bits/stdc++.h>
using namespace std;
const int maxn = 105;
struct edge{
    int u,v,w;
};
int f[maxn];
edge G[maxn*maxn];
int Find(int x){
    if(f[x]==x)return x;
    else return f[x]=Find(f[x]);
}
bool Same(int x,int y){
    return Find(x)==Find(y);
}
void Unionset(int x,int y){
    int u=Find(x),v=Find(y);
    if(u==v)return;
    else f[u]=v;
}
bool cmp(edge x,edge y){
    return x.w<y.w;
}
int main(){
    int n,k,tot=0,t=0,ans=0;
    cin>>n>>k;
    for(int i=1;i<=k;i++){
        scanf("%d%d%d",&G[i].u,&G[i].v,&G[i].w);
        tot+=G[i].w;
    }
    for(int i=1;i<=n;i++)f[i]=i;
    sort(G+1,G+1+k,cmp);
    for(int i=1;i<=k;i++){
        if(t==n-1)break;
        if(!Same(G[i].u,G[i].v)){
            Unionset(G[i].u,G[i].v);
            ans+=G[i].w;
            t++;
        }
    }
        
    cout<<tot-ans<<endl;
}

 

裸地最小生成树

标签:blog   cto   个数   size   ace   namespace   最优   ack   push   

原文地址:https://www.cnblogs.com/EdSheeran/p/8470125.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!