poj 最小生成树入门水题 1251 && 1258 && 1287 && 2395 && 2485 && 2377
2016-09-13 22:33
357 查看
1251:
裸最小生成树
1258:
同上
1287:
注意输入有多重边,只需保留最小权值。
2395:
输出最小生成树中的最长边
对kruskal算法略作修改,res由记录最小权值和改为记录最长边即可
2485:
同上。采用prim算法,172ms.....
2377:
稍作变形。最大生成树,若不能建树,输出-1。
裸最小生成树
#include<iostream>//660k 0ms #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<limits.h> using namespace std; const int maxe=20010; const int maxv=1009; struct edge{ int u,v,w; }es[maxe]; bool cmp(edge a,edge b){ return a.w<b.w; } int v,e; int par[maxv]; int rank[maxv]; void init(int n){ for(int i=0;i<n;++i){ par[i]=i; rank[i]=0; } } int find(int x){ int r=x,temp; while(r!=par[r]) r=par[r]; while(x!=r){//非递归路径压缩 temp=par[x]; par[x]=r; x=temp; } return r; } void unite(int x,int y){ x=find(x); y=find(y); if(x==y) return; if(rank[x]<rank[y]) par[x]=y; else{ par[y]=x; if(rank[x]==rank[y]) rank[x]++; } } bool same(int x,int y){ return find(x)==find(y); } int kruskal(){ sort(es,es+e,cmp); init(v); int res=0,sumv=0; for(int i=0;i<e;++i){ edge e=es[i]; if(sumv>=v-1) break; if(!same(e.u,e.v)){ unite(e.u,e.v); ++sumv; res+=e.w; } } return res; } int main(){ int n,te; char c[2];//chars c; 会报错.... 使用 char c[2] + c[0] 代替 while(scanf("%d",&v),v){ e=0; for(int i=0;i<v-1;++i){ scanf("%s%d",c,&n);//<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">或者scanf(" %c %d",&c,&n);+char c;</span> if(n==0) continue; else{ for(int j=0;j<n;++j){ scanf("%s%d",c,&te); es[e].u=i; es[e].v=c[0]-'A'; es[e++].w=te; } } } printf("%d\n",kruskal()); } return 0; }
1258:
同上
#include<stdio.h>//708k 16ms #include<iostream> #include<math.h> #include<algorithm> #include<string.h> using namespace std; #define maxv 110 #define inf 99999999 int v,cost[maxv][maxv],mincost[maxv]; bool used[maxv]; int prim(){ for(int i=0;i<v;++i){ mincost[i]=inf; used[i]=0; } mincost[0]=0; int res=0; while(1){ int j=-1; for(int i=0;i<v;++i){ if(!used[i]&&(mincost[i]<mincost[j]||j==-1)) j=i; } if(j==-1) break; used[j]=1; res+=mincost[j]; for(int i=0;i<v;++i){ mincost[i]=min(mincost[i],cost[j][i]); } } return res; } int main(){ while(~scanf("%d",&v)){ for(int i=0;i<v;++i){ for(int j=0;j<v;++j) scanf("%d",&cost[i][j]); } printf("%d\n",prim()); } return 0; }
1287:
注意输入有多重边,只需保留最小权值。
#include<stdio.h>//676k 16ms #include<iostream> #include<math.h> #include<algorithm> #include<string.h> using namespace std; const int maxv=60; const int inf=9999999; int v,e,cost[maxv][maxv],mincost[maxv]; bool used[maxv]; int prim(){ for(int i=1;i<=v;++i){ mincost[i]=inf; used[i]=0; } mincost[1]=0; int res=0; while(1){ int j=-1; for(int i=1;i<=v;++i){ if(!used[i]&&(mincost[i]<mincost[j]||j==-1)) j=i; } if(j==-1) break; used[j]=1; res+=mincost[j]; for(int i=1;i<=v;++i){ mincost[i]=min(mincost[i],cost[j][i]); } } return res; } int main(){ int a,b,c; while(~scanf("%d",&v),v){ scanf("%d",&e); if(!e) puts("0"); else{ for(int i=0;i<maxv;++i){ for(int j=0;j<maxv;++j){ cost[i][j]=inf; } } for(int i=1;i<=e;++i){ scanf("%d%d%d",&a,&b,&c); cost[a][b]=cost[b][a]=min(cost[a][b],c); } printf("%d\n",prim()); } } return 0; }
2395:
输出最小生成树中的最长边
对kruskal算法略作修改,res由记录最小权值和改为记录最长边即可
#include<iostream>//792k 47ms #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<limits.h> using namespace std; const int maxe=10010; const int maxv=2009; struct edge{ int u,v,w; }es[maxe]; bool cmp(edge a,edge b){ return a.w<b.w; } int v,e; int par[maxv]; int rank[maxv]; void init(int n){ for(int i=0;i<n;++i){ par[i]=i; rank[i]=0; } } int find(int x){ int r=x,temp; while(r!=par[r]) r=par[r]; while(x!=r){//非递归路径压缩 temp=par[x]; par[x]=r; x=temp; } return r; } void unite(int x,int y){ x=find(x); y=find(y); if(x==y) return; if(rank[x]<rank[y]) par[x]=y; else{ par[y]=x; if(rank[x]==rank[y]) rank[x]++; } } bool same(int x,int y){ return find(x)==find(y); } int kruskal(){ sort(es,es+e,cmp); init(v); int res=0,sumv=0; for(int i=0;i<e;++i){ edge e=es[i]; if(sumv>=v-1) break; if(!same(e.u,e.v)){ unite(e.u,e.v); ++sumv; res=max(res,e.w); } } return res; } int main(){ int a,b,c; while(~scanf("%d%d",&v,&e)){ for(int i=0;i<e;++i){ es[i].w=INT_MAX; scanf("%d%d%d",&a,&b,&c); es[i].u=a; es[i].v=b; es[i].w=min(es[i].w,c); } printf("%d\n",kruskal()); } return 0; }
2485:
同上。采用prim算法,172ms.....
#include<stdio.h> #include<iostream> #include<math.h> #include<algorithm> #include<string.h> using namespace std; #define maxv 520 #define inf 99999999 int v,cost[maxv][maxv],mincost[maxv]; bool used[maxv]; int prim(){ for(int i=0;i<v;++i){ mincost[i]=inf; used[i]=0; } mincost[0]=0; int res=0; while(1){ int j=-1; for(int i=0;i<v;++i){ if(!used[i]&&(mincost[i]<mincost[j]||j==-1)) j=i; } if(j==-1) break; used[j]=1; res=max(res,mincost[j]); // res+=mincost[j]; for(int i=0;i<v;++i){ mincost[i]=min(mincost[i],cost[j][i]); } } return res; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d",&v); for(int i=0;i<v;++i){ for(int j=0;j<v;++j) scanf("%d",&cost[i][j]); } printf("%d\n",prim()); } return 0; }
2377:
稍作变形。最大生成树,若不能建树,输出-1。
#include<iostream>//1196B 16ms #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<limits.h> using namespace std; const int maxe=20010; const int maxv=1009; struct edge{ int u,v,w; }es[maxe]; bool cmp(edge a,edge b){ return a.w>b.w; } int v,e; int par[maxv]; int rank[maxv]; void init(int n){ for(int i=0;i<n;++i){ par[i]=i; rank[i]=0; } } int find(int x){ int r=x,temp; while(r!=par[r]) r=par[r]; while(x!=r){//非递归路径压缩 temp=par[x]; par[x]=r; x=temp; } return r; } void unite(int x,int y){ x=find(x); y=find(y); if(x==y) return; if(rank[x]<rank[y]) par[x]=y; else{ par[y]=x; if(rank[x]==rank[y]) rank[x]++; } } bool same(int x,int y){ return find(x)==find(y); } int kruskal(){ sort(es,es+e,cmp); init(v); int res=0,sumv=0; for(int i=0;i<e;++i){ edge e=es[i]; if(sumv>=v-1) break; if(!same(e.u,e.v)){ unite(e.u,e.v); ++sumv; res+=e.w; } } if(sumv<v-1) res=-1; return res; } int main(){ int a,b,c; while(~scanf("%d%d",&v,&e)){ for(int i=0;i<e;++i){ es[i].w=INT_MIN; scanf("%d%d%d",&a,&b,&c); es[i].u=a; es[i].v=b; es[i].w=max(es[i].w,c); } printf("%d\n",kruskal()); } return 0; }
相关文章推荐
- poj 最小生成树入门水题 1251 && 1258 && 1287 && 2395 && 2485 && 2377
- POJ 2485 Highways (水题入门最小生成树)
- poj 1251 1258 2421 2485(最小生成树prime)
- POJ 1258 Agri-Net(最小生成树) && POJ 2377 Bad Cowtractors(最大生成树)
- POJ 1258--Agri-Net【最小生成树 && Kruskal && 水题】
- POJ 1258 Agri-Net 最小生成树 prim && kruskal
- POJ 1258 Agri-Net 最小生成树(Kruskal算法入门)
- POJ 1287 Networking (最小生成树入门)
- POJ 1258 Agri-Net 【最小生成树入门题目】
- POJ1258--贪心&最小生成树的prim算法
- poj 1251~最小生成树~入门
- poj 2395 Out of Hay、2485 Highways(求最小生成树的最长边)
- POJ 2421--Constructing Roads【水题 && 最小生成树 && kruskal】
- POJ 2031 && ZOJ 1718--Building a Space Station【最小生成树 && kurskal && 水题】
- poj&nbsp;1251&nbsp;Jungle&nbsp;Roads&nbsp;最小生成树
- poj 1287 Networking ->最小生成树
- poj2395--Out of Hay(最小生成树)
- hdu1301&poj1251 Jungle Roads(最小生成树之prim果题)
- hdoj_1102Constructing Roads(最小生成树)&& poj_2485Highways
- NYOJ 434 && POJ 1251 Jungle Roads(最小生成树)