ZOJ

题意:给出N个点,以及对应连接的费用邻接矩阵,每两个点之间连接还要额外花费 该节点的额外消费额 。问怎样连接 使得花费最小
思路:事实上我们在建立路径的时候就把 结点额外花费的值加进去就行了

krusal 题解:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=1e4;//点数
const int maxm=1e6+10;//边数
int pre[maxn];
int cost[maxn];
struct Edge{
    int u,v,w;
}edge[maxm];
int top; 
int cnt;
int ans;

void addedge(int u,int v,int w){
    edge[top].u=u;
    edge[top].v=v;
    edge[top++].w= w + cost[u] + cost[v];
} 
bool cmp(Edge a,Edge b) {
    return a.w<b.w; 
}
int find(int x)
{
    if(x!=pre[x]) return pre[x] = find(pre[x]);
    else return pre[x];
}
bool unite(int x,int y){
    int fx = find(x);
    int fy = find(y);
    if(fx!=fy) {
        pre[fx] = fy;
        cnt++;    
        return true;
    }
    else return false;
}
int Kruskal(int n){
    sort(edge,edge+top,cmp);//一次性把所有的边都排了 
    int u,v,w;
    for(int i=0;i<top;i++){
        u=edge[i].u;   
        v=edge[i].v;   
        w=edge[i].w; 
        if(unite(u,v)){
            ans += w;    
        }
        if(cnt==n-1) break;
    }
    if(cnt<n-1) return -1;
    return ans;
}
void init(int n){
    memset(edge,0,sizeof(edge));
    for(int i=0;i<=n;i++)
        pre[i] = i;
    ans = top = cnt = 0;
} 
int main(){
    int T;
    cin>>T;
    int n,m,w,a,b;
    while(T--){
        cin>>n;
        init(n);
        for(int i=1;i<=n;i++) cin>>cost[i];
        top=cnt=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                cin>>w;
                addedge(i,j,w);
            }
        }
        cout<<Kruskal(n)<<endl;
    }
    return 0;
}

prim 题解:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 1005;
const int maxm = 1e6+10;
int n,m;
int cost[maxn];
int ans;
typedef pair<int,int> pii;
struct Egde{
    int u,v,w,next;
}edge[maxm];
struct cmp{
    bool operator () (pii a, pii b){
        return a.first > b.first;
    }
};
int head[maxn];
int vis[maxn];
int dist[maxn];
int top;
void init(){
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
    memset(dist,-1,sizeof(dist));
    top = 0;
    ans = 0;
}
void add(int u,int v,int w){
    edge[top].u = u;
    edge[top].v = v;
    edge[top].w = w+ cost[u]+cost[v];
    edge[top].next = head[u];
    head[u] = top++;
}
void prim(int s){
    int i;
    priority_queue<pii,vector<pii>, cmp>q;
    vis[s] = 1;
    dist[s] = 0;
    for(i = head[s];~i;i = edge[i].next){
        int v = edge[i].v;
        dist[v] = edge[i].w;
        q.push(make_pair(dist[v],v));
    }
    while(!q.empty()){
        pii t = q.top();
        q.pop();
        if(vis[t.second]) continue;
        ans += t.first;
        vis[t.second] = 1;
        
        for(i = head[t.second]; ~i;i = edge[i].next){
        int v = edge[i].v;
        if(!vis[v]&&(dist[v]>edge[i].w)||dist[v] == -1){
            dist[v] = edge[i].w;
            q.push(make_pair(dist[v],v));
            }
        }        
    }
    
}
int main(){
    int T;
    cin>>T;
    int n,m,w,a,b;
    while(T--){
        cin>>n;
        init();
        for(int i=1;i<=n;i++) cin>>cost[i];
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                cin>>w;
                add(i,j,w);
            }
        }
        prim(1);
        cout<<ans<<endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Tianwell/p/11303765.html