标签:
A. POJ 1251 Jungle Roads
模板题
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; const int INF=(1<<29); map<char,int> STL; int edge[30][30]; int mincost[30]; bool used[30]; int n,m,from,to,w; int main() { for(int i=0;i<26;i++) STL[i+‘A‘]=i; while(cin>>n&&n) { char ch; int ed; for(int i=0;i<30;i++) for(int j=0;j<30;j++) { edge[i][j]=INF; used[i]=false; mincost[i]=INF; } for(int i=0;i<n-1;i++) { cin>>ch>>m; for(int j=0;j<m;j++) { cin>>ch>>ed; edge[i][STL[ch]]=edge[STL[ch]][i]=min(edge[i][STL[ch]],ed); } } int res=0; mincost[0]=0; while(1) { int v=-1; for(int u=0;u<n;u++) if(!used[u]&&(mincost[v]>mincost[u]||v==-1)) v=u; if(v==-1) break; used[v]=true; res+=mincost[v]; for(int u=0;u<n;u++) mincost[u]=min(mincost[u],edge[v][u]); } printf("%d\n",res); } return 0; }
B. POJ 1287 Networking
模板题
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> #define INF 1000000000 using namespace std; int edge[55][55]; int d[55]; bool used[55]; int n,m,from,to,w; int main() { while(scanf("%d",&n)&&n) { scanf("%d",&m); for(int i=0;i<55;i++) for(int j=0;j<55;j++) edge[i][j]=INF; for(int i=1;i<55;i++) { d[i]=INF; used[i]=false; } for(int i=0;i<m;i++) { scanf("%d%d%d",&from,&to,&w); edge[to][from]=edge[from][to]=min(edge[to][from],w); } d[1]=0; int res=0; while(1) { int v=-1; for(int u=1;u<=n;u++) if(!used[u]&&(v==-1||d[u]<d[v])) v=u; if(v==-1) break; used[v]=true; res+=d[v]; for(int u=1;u<=n;u++) d[u]=min(d[u],edge[u][v]); } printf("%d\n",res); } return 0; }
C. POJ 2031 Building a Space Station
题意:有n个空间站,告诉你它们的三维坐标以及半径,你需要把他们都连接起来。
思路:设半径分别为r1,r2,空间站距离为d。如果的d<=r1+r2,那么连一条权值为0的边,如果d>r1+r2就连一条距离为d-r1-r2的边。然后套模板就好。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; double dist[110][110]; double mincost[110]; bool used[110]; struct Point{ double x,y,z,r; }point[110]; double fun(int i,int j) { Point a=point[i]; Point b=point[j]; double d=sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)+(a.z-b.z)*(a.z-b.z)); return (d>a.r+b.r)?d-a.r-b.r:0; } int n; int main() { while(cin>>n&&n) { memset(point,0,sizeof(point)); for(int i=0;i<n;i++) { used[i]=false; mincost[i]=1000.0; } for(int i=0;i<n;i++) { cin>>point[i].x>>point[i].y>>point[i].z>>point[i].r; for(int j=0;j<i;j++) dist[i][j]=dist[j][i]=fun(i,j); } double res=0; mincost[0]=0; while(1) { int v=-1; for(int u=0;u<n;u++) if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u; if(v==-1) break; used[v]=1; res+=mincost[v]; for(int u=0;u<n;u++) mincost[u]=min(mincost[u],dist[u][v]); } printf("%.3f\n",res); } return 0; }
D. POJ 2421 Constructing Roads
题意:有n个村庄,Q条修好的路,给你n个村庄的邻接矩阵,问你最小生成树是多少。
思路:在邻接矩阵中把已有的路的两个节点的距离改为0。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; int dist[110][110]; int mincost[110]; bool used[110]; int n,Q; int main() { while(cin>>n&&n) { for(int i=0;i<=n;i++) { used[i]=false; mincost[i]=1000000; } for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cin>>dist[i][j]; cin>>Q; for(int i=0;i<Q;i++) { int a,b; cin>>a>>b; dist[a][b]=dist[b][a]=0; } int res=0; mincost[1]=0; while(1) { int v=-1; for(int u=1;u<=n;u++) if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u; if(v==-1) break; used[v]=1; res+=mincost[v]; for(int u=1;u<=n;u++) mincost[u]=min(mincost[u],dist[u][v]); } printf("%d\n",res); } return 0; }
E. ZOJ 1586 QS Network
题意:在光缆的价格矩阵上加上这两个节点所喜欢的插头的价格就行。然后直接裸的最小生成树。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; int dist[1010][1010]; int mincost[1010]; bool used[1010]; int T,n; int main() { cin>>T; while(T--) { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&mincost[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d",&dist[i][j]); if(i!=j) dist[i][j]=dist[i][j]+mincost[i]+mincost[j]; } for(int i=1;i<=n;i++) { used[i]=false; mincost[i]=(1<<29); } int res=0; mincost[1]=0; while(1) { int v=-1; for(int u=1;u<=n;u++) if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u; if(v==-1) break; used[v]=1; res+=mincost[v]; for(int u=1;u<=n;u++) mincost[u]=min(mincost[u],dist[v][u]); } printf("%d\n",res); } return 0; }
F. POJ 1789 Truck History
题意: 每种卡车都有一个编号,一个编号只能由另一个编号变化过来,变化的代价就是两个编号相同位置字母不同的位置的个数。
思路: 其实就是一个完全图,求最小生成树。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> #define INF 10 using namespace std; char str[2010][10]; int edge[2010][2010]; int mincost[2010]; bool used[2010]; int fun(int i,int j) { int ans=0; for(int k=0;k<7;k++) if(str[i][k]!=str[j][k]) ans++; return ans; } int main() { int n; while(scanf("%d",&n)&&n) { for(int i=0;i<n;i++) { scanf("%s",str[i]); for(int j=0;j<i;j++) { edge[j][i]=edge[i][j]=fun(i,j); } } for(int i=0;i<n;i++) { mincost[i]=INF; used[i]=false; } mincost[0]=0; int res=0; while(1) { int v=-1; for(int u=0;u<n;u++) if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u; if(v==-1) break; used[v]=true; res+=mincost[v]; for(int u=0;u<n;u++) mincost[u]=min(mincost[u],edge[v][u]); } printf("The highest possible quality is 1/%d.\n",res); } return 0; }
G. POJ 2349 Arctic Network
题意:有n个前哨战,每一个前哨站可以跟其他前哨站交流,花费为他们的距离。同时你拥有s个卫星,任意两个有卫星的前哨站可以直接交流,没有花费。问你所需要的最小花费是多少,最小花费为最小生成树中最长的边。
思路:转化题意,实际上就是求最短路中第s+1长的边。可以prim也可以kruskal,实际上kruskal应该更简单。我这里写的是prim。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; double dist[550][550]; double mincost[550]; bool used[550]; struct Point{ int x,y; }point[550]; double fun(int i,int j) { return sqrt((point[i].x-point[j].x)*(point[i].x-point[j].x)*1.0+(point[i].y-point[j].y)*(point[i].y-point[j].y)*1.0); } int T,n,m; int main() { cin>>T; while(T--) { int from,to,w,s,p; cin>>s>>p; for(int i=0;i<p;i++) { cin>>point[i].x>>point[i].y; for(int j=0;j<i;j++) dist[i][j]=dist[j][i]=fun(i,j); } for(int i=0;i<p;i++) { used[i]=false; mincost[i]=100000000.0; } mincost[0]=0; int cnt=0; while(1) { int v=-1; cnt++; for(int u=0;u<p;u++) if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u; if(v==-1) break; used[v]=1; for(int u=0;u<p;u++) if(v!=u&&!used[u]) mincost[u]=min(mincost[u],dist[v][u]); } sort(mincost,mincost+p); printf("%.2f\n",mincost[p-s]); } return 0; }
H. POJ 1751 Highways
题意:有n个塔,现在在塔之间已经有m条高速公路了,你需要加上高速公路,使得他们任意两点间可达,问你需要的花费是多少。
思路:把已有的边的权值设为0,然后求一遍最小生成树就好。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; int T,n,m,cnt; double dist[800][800]; double mincost[800]; int ans[800]; int par[11000]; int rank[11000]; bool used[800]; struct Point{ int x,y; }point[800]; double fun(int i,int j) { return sqrt((point[i].x-point[j].x)*(point[i].x-point[j].x)+(point[i].y-point[j].y)*(point[i].y-point[j].y)); } int main() { while(cin>>n) { int from,to,w; cnt=0; memset(dist,0,sizeof(dist)); memset(used,0,sizeof(used)); for(int i=0;i<=n;i++) { mincost[i]=1000000000.0; ans[i]=i; } for(int i=1;i<=n;i++) { cin>>point[i].x>>point[i].y; for(int j=1;j<i;j++) dist[j][i]=dist[i][j]=fun(i,j); } cin>>m; for(int i=0;i<m;i++) { cin>>from>>to; dist[from][to]=dist[to][from]=0; } //sort(ed,ed+m,comp); //ans=kruskal(-1); int last=1; mincost[1]=0; while(1) { int v=-1; for(int u=1;u<=n;u++) if(!used[u]&&(mincost[u]<mincost[v]||v==-1)) v=u; if(v==-1) break; used[v]=true; if(mincost[v]) printf("%d %d\n",ans[v],v); for(int u=1;u<=n;u++) if(mincost[u]>dist[u][v]) { mincost[u]=min(mincost[u],dist[u][v]); ans[u]=v; } } } return 0; }
I. POJ 1258 Agri-Net
题意:输入一个矩阵,求最小生成树。裸题。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; int T,n,m,cnt; int dist[110][110]; int mincost[110]; int par[11000]; int rank[11000]; bool used[11000]; struct edge{ int from,to,w; }ed[11000]; bool comp(edge a,edge b) { return a.w<b.w; } void inti(int n) { for(int i=0;i<=n;i++) { par[i]=i; rank[i]=0; } } int find(int x) { if(par[x]==x) return x; return par[x]=find(par[x]); } 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(int d) { inti(110); int res=0; for(int i=0;i<m;i++) { edge e=ed[i]; if(!same(e.from,e.to)&&i!=d) { if(d==-1) used[cnt++]=i; unite(e.from,e.to); res+=e.w; } } return res; } int main() { while(cin>>n) { int from,to,w,ans,flag=0; cnt=0; memset(dist,0,sizeof(dist)); memset(used,0,sizeof(used)); for(int i=0;i<n;i++) mincost[i]=1000000100; for(int i=0;i<n;i++) for(int j=0;j<n;j++) cin>>dist[i][j]; //sort(ed,ed+m,comp); //ans=kruskal(-1); int res=0; mincost[0]=0; while(1) { int v=-1; for(int u=0;u<n;u++) if(!used[u]&&(mincost[u]<mincost[v]||v==-1)) v=u; if(v==-1) break; used[v]=true; res+=mincost[v]; for(int u=0;u<n;u++) mincost[u]=min(mincost[u],dist[u][v]); } printf("%d\n",res); } return 0; }
J. POJ 3026 Borg Maze
题意:在一个迷宫内有数个A点,你需要从S点到达N点问你最小花费是多少。
思路:对所有的S点和A点进行一次bfs,求出任意两点之间的最短距离,然后最小生成树。注意输入,有陷阱。
#include <stdio.h> #include <iostream> #include <queue> using namespace std; #define MAXV 102 #define inf 1<<29 typedef struct{ int x,y; }Point; Point point[MAXV]; char s[MAXV][MAXV]; int m,n,psum,map[MAXV][MAXV]; int mincost[MAXV]; int used[MAXV]; int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; void findpoint(){ int i,j; psum=1; for(i=0;i<m;i++) for(j=0;j<n;j++) if(s[i][j]==‘A‘){ point[psum].x=i; point[psum++].y=j; }else if(s[i][j]==‘S‘){ point[0].x=i; point[0].y=j; } } void bfs(int start){ int discover[MAXV][MAXV],dis[MAXV][MAXV]; queue <int> q; int i,a,b,tx,ty; for(i=0;i<m;i++) for(int j=0;j<n;j++){ dis[i][j]=0; discover[i][j]=0; } a=point[start].x; b=point[start].y; q.push(a); q.push(b); discover[a][b]=true; while(!q.empty()){ a=q.front();q.pop(); b=q.front();q.pop(); for(i=0;i<4;i++){ tx=a+dx[i]; ty=b+dy[i]; if(!discover[tx][ty] && tx>=0 && tx<n && ty>=0 && ty<m && s[tx][ty]!=‘#‘){ dis[tx][ty]=dis[a][b]+1; discover[tx][ty]=true; q.push(tx); q.push(ty); } } } for(i=0;i<psum;i++){ int t=dis[point[i].x][point[i].y]; if(t) map[start][i]=t; } } void prim(){ int i,j,v; int d[MAXV],vis[MAXV]; for(i=0;i<psum;i++){ d[i]=map[0][i]; vis[i]=0; } for(i=0;i<psum;i++){ int min=inf; for(j=0;j<psum;j++) if(!vis[j] && d[j]<min){ min=d[j]; v=j; } vis[v]=1; for(j=0;j<psum;j++){ if(!vis[j] && map[v][j]<d[j]) d[j]=map[v][j]; } } int ans=0; for(i=0;i<psum;i++) ans+=d[i]; printf("%d\n",ans); } int main(){ int t,i; scanf("%d\n",&t); while(t--){ gets(s[0]); sscanf(s[0],"%d%d",&n,&m); for(i=0;i<m;i++) gets(s[i]); findpoint(); //找到点的坐标 for(i=0;i<psum;i++) bfs(i); //计算距离 for(int i=0;i<psum;i++) { mincost[i]=1000000000; used[i]=false; } int res=0; mincost[0]=0; while(1) { int v=-1; for(int u=0;u<psum;u++) if(!used[u]&&(mincost[u]<mincost[v]||v==-1)) v=u; if(v==-1) break; used[v]=true; res+=mincost[v]; for(int u=0;u<psum;u++) mincost[u]=min(mincost[u],map[v][u]); } printf("%d\n",res); //最小生成树 } return 0; }
K. POJ 1679 The Unique MST
题意:问你最小生成树是不是唯一的。
参看:http://www.cnblogs.com/onlyAzha/p/4793031.html 次小生成树的两种做法。
L. HDU 1233 还是畅通工程
模板题
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; int dist[110][110]; int mincost[110]; bool used[110]; struct Point{ int x,y; }point[110]; double fun(int i,int j) { return sqrt((point[i].x-point[j].x)*(point[i].x-point[j].x)*1.0+(point[i].y-point[j].y)*(point[i].y-point[j].y)*1.0); } int T,n; int main() { while(scanf("%d",&n)&&n) { int from,to,w; for(int i=0;i<n*(n-1)/2;i++) { scanf("%d%d%d",&from,&to,&w); dist[from][to]=dist[to][from]=w; } for(int i=1;i<=n;i++) { used[i]=false; mincost[i]=100000000; } int res=0; mincost[1]=0; while(1) { int v=-1; for(int u=1;u<=n;u++) if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u; if(v==-1) break; used[v]=1; res+=mincost[v]; for(int u=1;u<=n;u++) mincost[u]=min(mincost[u],dist[v][u]); } printf("%d\n",res); } return 0; }
N. HDU 1875 畅通工程再续
题意:n个点,任意两个距离不小于10也不大于1000的岛都可以连一条权值为距离*100的边,然后最小生成树。
#include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> #include<vector> #include<string> #include<map> #include<queue> #include<set> using namespace std; double dist[110][110]; double mincost[110]; bool used[110]; struct Point{ int x,y; }point[110]; double fun(int i,int j) { return sqrt((point[i].x-point[j].x)*(point[i].x-point[j].x)*1.0+(point[i].y-point[j].y)*(point[i].y-point[j].y)*1.0); } int T,n; int main() { cin>>T; while(T--) { int flag=0; cin>>n; for(int i=1;i<=n;i++) { cin>>point[i].x>>point[i].y; for(int j=1;j<i;j++) dist[i][j]=dist[j][i]=fun(i,j); } for(int i=1;i<=n;i++) { flag=0; for(int j=1;j<=n;j++) { if(i!=j&&(10.0<=dist[i][j]&&dist[i][j]<=1000.0)) flag=1; if(i!=j&&dist[i][j]<10) dist[i][j]=1000.0; } if(!flag) break; } if(!flag) { printf("oh!\n"); continue; } for(int i=1;i<=n;i++) { used[i]=false; mincost[i]=100000000.0; } double res=0; mincost[1]=0.0; while(1) { int v=-1; for(int u=1;u<=n;u++) if(!used[u]&&(v==-1||mincost[u]<mincost[v])) v=u; if(v==-1) break; used[v]=1; res+=mincost[v]; for(int u=1;u<=n;u++) mincost[u]=min(mincost[u],dist[v][u]); } printf("%.1f\n",res*100); } return 0; }
标签:
原文地址:http://www.cnblogs.com/onlyAzha/p/4745070.html