题意:给出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; }