度限制最小生成树 POJ 1639 贪心+DFS+prim
2013-08-10 16:38
453 查看
很好的解题报告:
http://blog.csdn.net/new_c_yuer/article/details/6365689
注意两点:
1.预处理环中权值最大的边····
2.可以把去掉度限制后的点看成是连通的,权值为无穷远的点也看做是连通的,反正后面肯定会替换出来的····
我的代码没有预处理出权值最大的边,但是第2点事做到了的,这样便于代码的实现·····
贴代码:
View Code
http://blog.csdn.net/new_c_yuer/article/details/6365689
注意两点:
1.预处理环中权值最大的边····
2.可以把去掉度限制后的点看成是连通的,权值为无穷远的点也看做是连通的,反正后面肯定会替换出来的····
我的代码没有预处理出权值最大的边,但是第2点事做到了的,这样便于代码的实现·····
贴代码:
#include <cstdio> #include <iostream> #include <map> #include <string> #include <algorithm> #define INF 0x3f3f3f3f #define N 505 using namespace std; map<string,int> ma; map<string,int>::iterator it; int n,k;//点的个数,度数限制 bool flag; long long int ans;//最后的结果 bool in ,vis ;//加入最小生成树中的边 int edge ,pre , next ,lowcost ;//边,确定哪些边被加入了最小生成树中,存环中的边,求最小生成树 int Find(char c[]) { it = ma.find(c); if(it != ma.end()) return it->second; ma[c] = ++n; return n; } //用prim函数求一次去掉度限制的点后的最小生成树 void prim() { lowcost[1] = -1; for(int i=2; i<=n; ++i) { lowcost[i] = edge[1][i]; pre[i] = 1; } for(int i=2; i<=n; ++i) { int v; int minum=INF; for(int j=2; j<=n; ++j) { if(lowcost[j] != -1 && minum >= lowcost[j]) { minum = lowcost[j]; v = j; } } lowcost[v] = -1; ans += edge[v][pre[v]]; in[v][pre[v]] = in[pre[v]][v] = 1; for(int j=2; j<=n; ++j) { if(lowcost[j] != -1 && lowcost[j] > edge[j][v] ) { lowcost[j] = edge[j][v]; pre[j] = v; } } } } //dfs找出环 void dfs(int x) { if(x == 0) { flag = true; return; } vis[x] = 1; for(int i = n; i >= 0; --i) { if(in[x][i] && !vis[i] && !flag) { next[x] = i; dfs(i); } } } //找环上权值最大的边 void findMax(int x,int &s,int &e,int &maxnum) { memset(vis,0,sizeof(vis)); flag = false; dfs(x); maxnum = edge[0][x]; int ne = x; while(next[ne] != 0) { if(edge[ne][next[ne]] > maxnum) { maxnum = edge[ne][next[ne]]; s = ne; e = next[ne]; } ne = next[ne]; } } //找度限制为k的最小生成树 void kTree() { int minum = INF; int v; for(int i=1; i<=n; ++i) { if(edge[0][i] < minum) { minum = edge[0][i]; v = i; } } in[v][0] = in[0][v] = 1; ans += edge[0][v]; for(int t=1; t<k; ++t) { minum = INF; v = -1; int s,e,m; for(int i=1; i<=n; ++i) { if(!in[0][i] && edge[0][i] < INF) { int ss,ee,maxnum; findMax(i,ss,ee,maxnum); if(edge[0][i] - maxnum < minum) { minum = edge[0][i] - maxnum ; s = ss; e = ee; m = minum; v= i; } } } if(v == -1) break; if(minum >= 0 ) break; in[0][v] = 1; in[v][0] = 1; in[s][e] = 0; in[e][s] =0; ans += minum; } printf("Total miles driven: %d\n",ans); } // 初始化输入 void initScan() { int m; ma["Park"] = n; scanf("%d",&m); memset(edge,0x3f,sizeof(edge)); for(int i=0; i<m; ++i) { char a1 ,a2 ; int u,v,w; scanf("%s %s %d",a1,a2,&w); u = Find(a1); v = Find(a2); edge[u][v] = w; edge[v][u] = edge[u][v]; } scanf("%d",&k); } int main() { initScan(); prim(); kTree(); return 0; }
View Code
相关文章推荐
- POJ 1639 度限制最小生成树Prim
- POJ 1639 Picnic Planning (k度限制最小生成树)
- poj1639 Picnic Planning 最小度数限制生成树
- POJ 1639 Picnic Planning【度限制最小生成树】
- POJ 1639 Picnic Planning(最小度限制生成树)
- poj_1639 Picnic Planning(度限制最小生成树)
- POJ-1639 Picnic Planning (最小度限制生成树)(模板题)
- POJ 1639 Picnic Planning(初遇最小度限制生成树)
- POJ 1639:Picnic Planning(最小度限制生成树)
- poj1639 Picnic Planning 最小度数限制生成树
- poj 1639 Picnic Planning(最小K度限制生成树)
- poj 1639 有限制的最小生成树
- POJ 1639 Picnic Planning 【最小度限制生成树】
- poj1639 Picnic Planning 最小度数限制生成树
- poj 1639 最小度限制生成树
- 【POJ 1639】 Picnic Planning (最小k度限制生成树)
- poj 1639 Picnic Planning 最小K度限制生成树
- POJ 1639 Picnic Planning(度限制最小生成树)
- POJ 1639 度限制的最小生成树
- POJ1639 Picnic Planning —— 根节点度数有限制的最小生成树