Time Limit: 1000MS | Memory Limit: 10000K | |
Description
Input
Output
Sample Input
4 0 4 9 21 4 0 8 17 9 8 0 16 21 17 16 0
Sample Output
28
开始学最小生成树了,照着郭老师的代码敲了一边,第一次交还错了。。。不过发现了二维vector的clear()函数的正确使用方法
#include <cstdio> #include <cstring> #include <queue> #include <vector> #include <algorithm> using namespace std; const int INF=0x3f3f3f3f; struct Edge{ int v,w;//v表示边端点,另一个端点已知;w表示边权值,也表示v到最小生成树的距离 Edge(int vv=0,int ww=INF):v(vv),w(ww) {} bool operator < (const Edge& a) const { return w>a.w; } }u; int n,dis[105],ans,cnt;//dis表示各顶点到最小生成树的距离 bool vis[105];//vis表示各顶点是否已被加入最小生成树 vector<vector<Edge> > g(105);//邻接表 void prim() {//prim算法求最小生成树 int i,j,v,w; priority_queue<Edge> q;//存放顶点及其到最小生成树的距离 memset(vis,false,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); cnt=ans=0;//cnt表示已被加入最小生成树的顶点数;ans表示最小生成树的总权值 q.push(Edge(0,0));//开始只有顶点0,它到最小生成树的距离为0 while(cnt<n&&!q.empty()) { do {//每次从队列里面拿离最小生成树最近的点 u=q.top(); q.pop(); }while(vis[u.v]&&!q.empty()); if(!vis[u.v]) { ans+=u.w; vis[u.v]=true; ++cnt; 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)); } } } } //若此时cnt<n,则图不连通 } int main() { int i,j,w; while(1==scanf("%d",&n)) { /*g.clear(); //或者最外层一维清空并且对最外层resize() g.resize(n+1);*/ for(i=0;i<n;++i) { g[i].clear();//必须最内层每一维单独清空才能清空所有数据 for(j=0;j<n;++j) { scanf("%d",&w); g[i].push_back(Edge(j,w)); } } prim(); printf("%d\n",ans); } return 0; }