题意:给出一张图然后求最小生成树
输入:N个点(输入以0结尾),然后对应N个点相连的 边数m, 以及对应指向的结点 以及权值
思路:采用prim算法来做,先类似于dijsktra,搜索集合外点的路径,最小的路径然后加更新集合。再采用优先队列优化,减小每次判断要路径权值大小
完整代码:
#include <iostream> #include <cstdio> #include <vector> #include <cstring> #include <string> #include <queue> using namespace std; typedef pair<int,int> pii; const int maxm = 1e5; const int inf = 0x3f3f3f3f; const int maxn = 30; int top; int n,m; int ans; int head[maxn]; int vis[maxn]; int dist[maxn]; //堆重载 struct cmp{ bool operator() (pii a, pii b){ return a.first>b.first; } }; struct Edge{ int u,v,w; int next; }edge[maxm]; void init(){ memset(head,-1,sizeof(head)); memset(edge,0,sizeof(edge)); memset(dist,-1,sizeof(dist)); memset(vis,0,sizeof(vis)); top = 0; ans = 0; } void add(int v,int u,int w){ edge[top].u = u; edge[top].v = v; edge[top].w = w; edge[top].next = head[u]; head[u] = top++; } void prim(int s){ int i; priority_queue<pii,vector<pii> ,cmp>Q; dist[s] = 0; vis[s] = 1; for(i = head[s]; ~i; i = edge[i].next){ //先把到起点边的距离初始化为其本身 dist[edge[i].v] = edge[i].w; Q.push(make_pair(dist[edge[i].v],edge[i].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 j = edge[i].v; //没被访问没有连接或者权值太小 if(!vis[j]&&(dist[j]>edge[i].w||dist[j]==-1)){ dist[j] = edge[i].w; Q.push(make_pair(dist[j],j)); } } } } int main(){ while(cin>>n&&n){ init(); int w; char ch,op; for(int i=0;i<n-1;i++){ cin>>ch; cin>>m; for(int j=0;j<m;j++){ cin>>op>>w; add(ch-'A',op-'A',w); add(op-'A',ch-'A',w); } } prim(0); cout<<ans<<endl; } }