3 1 2 1 0 1 3 2 0 2 3 4 0 3 1 2 1 0 1 3 2 0 2 3 4 1 3 1 2 1 0 1 3 2 1 2 3 4 1 0
3 1 0
刚开始还想直接将建好的边的点压入队列,但感觉比较麻烦。然后就想到如果边已存在,则将其权值设为0,然后就变成裸的最小生成树。
#include <cstdio> #include <cstring> #include <queue> #include <vector> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; struct Edge { int v,w; Edge(int vv=0,int ww=INF):v(vv),w(ww) {} bool operator < (const Edge& a) const { return w>a.w; } }u; int n,cnt,ans,vis[105],dis[105]; priority_queue <Edge> q; vector<vector<Edge> > g; void Prim() { int i,j,v,w; q.push(Edge(1,0)); memset(vis,false,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); ans=cnt=0; while(!q.empty()) { u=q.top(); q.pop(); if(!vis[u.v]) { vis[u.v]=true; ++cnt; ans+=u.w; for(i=0,j=g[u.v].size();i<j;++i) if(!vis[v=g[u.v][i].v]&&dis[v]>(w=g[u.v][i].w)) { dis[v]=w; q.push(Edge(v,w)); } } } } int main() { int i,s,e,cst,cond,t; while(scanf("%d",&n),n) { g.clear(); g.resize(n+1); for(i=0,t=(n*(n-1))>>1;i<t;++i) { scanf("%d%d%d%d",&s,&e,&cst,&cond); g[s].push_back(Edge(e,cond==1?0:cst));//如果道路已建,则权值为0 g[e].push_back(Edge(s,cond==1?0:cst)); } Prim(); printf("%d\n",ans); } return 0; }