A & M - Jungle Roads HDU - 1301
题意:字母之间的路,求最小生成树
题解:处理好建边以后就是一个Prime

#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<stack> #include<cstdlib> #include <vector> #include <set> #include<queue> #include<map> using namespace std; #define ll long long #define llu unsigned long long #define INF 0x3f3f3f3f #define PI acos(-1.0) const int maxn = 50; const ll mod = 1e9+7; const double eps = 1e-8; bool vis[maxn]; int lowc[maxn]; int Prim(int cost[][maxn],int n) { int ans = 0; memset(vis,false,sizeof vis); vis[0] = true; for(int i=1;i<n;i++) lowc[i] = cost[0][i]; for(int i=1;i<n;i++) { int minc = INF; int p = -1; for(int j=0;j<n;j++) { if(!vis[j] && minc > lowc[j]) { minc = lowc[j]; p = j; } } if(minc == INF) return -1; ans += minc; vis[p] = true; for(int j=0;j<n;j++) if(!vis[j] && lowc[j] > cost[p][j]) lowc[j] = cost[p][j]; } return ans; } int main() { int n; while(scanf("%d",&n) && n) { int cost[maxn][maxn]; for(int i=0;i<maxn;i++) { for(int j=0;j<maxn;j++) if(i == j) cost[i][j] = 0; else cost[i][j] = INF; } for(int i=1;i<n;i++) { char a; cin>>a; int num; cin>>num; for(int i=0;i<num;i++) { char ch; int len; cin>>ch>>len; cost[a-'A'][ch-'A'] = len; cost[ch-'A'][a-'A'] = len; } } int ans = Prim(cost,n); cout<<ans<<endl; } }
B - Networking POJ - 1287
题意:有重复边的跑最小生成树
题解:边取小跑Prime

#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<stack> #include<cstdlib> #include <vector> #include <set> #include<queue> using namespace std; #define ll long long #define llu unsigned long long #define INF 0x3f3f3f3f #define PI acos(-1.0) const int maxn = 1e2+5; bool vis[maxn]; int lowc[maxn]; int Prim(int cost[][maxn],int n) { int ans = 0; memset(vis,false,sizeof vis); vis[1] = true; for(int i=2;i<=n;i++) lowc[i] = cost[1][i]; for(int i=2;i<=n;i++) { int minc = INF; int p = -1; for(int j=1;j<=n;j++) if(!vis[j] && minc > lowc[j]) { minc = lowc[j]; p = j; } if(minc == INF) return -1; ans += minc; vis[p] = true; for(int j=1;j<=n;j++) if(!vis[j] && lowc[j] > cost[p][j]) lowc[j] = cost[p][j]; } return ans; } int main() { int n,m; while(scanf("%d",&n) && n) { scanf("%d",&m); int cost[maxn][maxn]; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i == j) cost[i][j] = 0; else cost[i][j] = INF; for(int i=0;i<m;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); cost[a][b] = min(cost[a][b],c); cost[b][a] = min(cost[b][a],c); cost[a][b] = cost[b][a] = min(cost[a][b],cost[b][a]); } int ans = Prim(cost,n); printf("%d ",ans); } }
C - Building a Space Station POJ - 2031
题意:三维上的球上建最小生成树
题解:处理边即可

#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<stack> #include<cstdlib> #include <vector> #include <set> #include<queue> using namespace std; #define ll long long #define llu unsigned long long #define INF 0x3f3f3f3f #define PI acos(-1.0) const int maxn = 1e2+5; struct node { double x,y,z,r; }a[maxn]; double dis(double x1,double y1,double z1,double r1,double x2,double y2,double z2,double r2) { double len = (x1-x2)*(x1-x2) + (y1-y2)*(y1-y2) + (z1-z2)*(z1-z2); double ans = sqrt(len) - r1 - r2; return max(0.0,ans); } bool vis[maxn]; double lowc[maxn]; double Prime(double cost[][maxn],int n) { double ans = 0; memset(vis,0,sizeof vis); vis[0] = true; for(int i=1;i<n;i++) lowc[i] = cost[0][i]; for(int i=1;i<n;i++) { double minc = 9999999999.9; int p = -1; for(int j=0;j<n;j++) if(!vis[j] && minc > lowc[j]) { p = j; minc = lowc[j]; } ans += minc; vis[p] = true; for(int j=0;j<n;j++) if(!vis[j] && lowc[j] > cost[p][j]) lowc[j] = cost[p][j]; } return ans; } int main() { int n; while(scanf("%d",&n) && n) { double cost[maxn][maxn]; for(int i=0;i<n;i++) scanf("%lf %lf %lf %lf",&a[i].x,&a[i].y,&a[i].z,&a[i].r); for(int i=0;i<n;i++) for(int j=0;j<n;j++) cost[i][j] = dis(a[i].x,a[i].y,a[i].z,a[i].r,a[j].x,a[j].y,a[j].z,a[j].r); double ans = Prime(cost,n); printf("%.3f ",ans); } }
D - Constructing Roads POJ - 2421
题意:邻接矩阵有些边权值为0,求最小生成树
题解:Prim

#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<stack> #include<cstdlib> #include <vector> #include <set> #include<queue> using namespace std; #define ll long long #define llu unsigned long long #define INF 0x3f3f3f3f #define PI acos(-1.0) const int maxn = 1e2+5; int vis[maxn]; int lowc[maxn]; int cost[maxn][maxn]; int Prim(int cost[][maxn],int n) { int ans = 0; memset(vis,0,sizeof vis); vis[1] = true; for(int i=2;i<=n;i++) lowc[i] = cost[1][i]; for(int i=2;i<=n;i++) { int minc = INF; int p = -1; for(int j=1;j<=n;j++) if(!vis[j] && minc > lowc[j]) { minc = lowc[j]; p = j; } ans += minc; vis[p] = true; for(int j=1;j<=n;j++) if(!vis[j] && lowc[j] > cost[p][j]) lowc[j] = cost[p][j]; } return ans; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&cost[i][j]); int q; scanf("%d",&q); for(int i=0;i<q;i++) { int a,b; scanf("%d%d",&a,&b); cost[a][b] = cost[b][a] = 0; } int ans = Prim(cost,n); printf("%d ",ans); }
E - QS Network ZOJ - 1586
题意:最小生出树,边的值还需要加上两个顶点的值
题解:只需要将顶点的值加到其权值上即可

#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<stack> #include<cstdlib> #include <vector> #include <set> #include<queue> using namespace std; #define ll long long #define llu unsigned long long #define INF 0x3f3f3f3f #define PI acos(-1.0) const int maxn = 1e3+5; bool vis[maxn]; int lowc[maxn]; int cost[maxn][maxn]; int a[maxn]; int prim(int cost[][maxn],int n) { int ans = 0 ; memset(vis,false,sizeof vis); vis[1] = true; for(int i=2;i<=n;i++) lowc[i] = cost[1][i]; for(int i=2;i<=n;i++) { int minc = INF; int p = -1; for(int j=1;j<=n;j++) { if(!vis[j] && minc > lowc[j]) { minc = lowc[j]; p = j; } } ans += minc; vis[p] = true; for(int j=1;j<=n;j++) if(!vis[j] && lowc[j] > cost[p][j]) lowc[j] = cost[p][j]; } return ans; } int main() { int t; scanf("%d",&t); while(t--) { int n; int ans = 0; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { scanf("%d", &cost[i][j]); cost[i][j] += a[i] + a[j]; } ans += prim(cost,n); printf("%d ",ans); } }
F - Truck History POJ - 1789
题意:两个字符串之间不同的个数为边的权值,跑最小生成树
题解:处理边之后跑最小生成树

#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<stack> #include<cstdlib> #include <vector> #include <set> #include<queue> using namespace std; #define ll long long #define llu unsigned long long #define INF 0x3f3f3f3f #define PI acos(-1.0) const int maxn = 2e3+5; bool vis[maxn]; int lowc[maxn]; int cost[maxn][maxn]; int a[maxn]; int prim(int cost[][maxn],int n) { int ans = 0 ; memset(vis,false,sizeof vis); vis[1] = true; for(int i=2;i<=n;i++) lowc[i] = cost[1][i]; for(int i=2;i<=n;i++) { int minc = INF; int p = -1; for(int j=1;j<=n;j++) { if(!vis[j] && minc > lowc[j]) { minc = lowc[j]; p = j; } } ans += minc; vis[p] = true; for(int j=1;j<=n;j++) if(!vis[j] && lowc[j] > cost[p][j]) lowc[j] = cost[p][j]; } return ans; } int main() { int n; while(scanf("%d",&n) && n) { char str[maxn][10]; for(int i=1;i<=n;i++) scanf("%s",str[i]); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { int tmp = 0; for(int k=0;k<7;k++) if(str[i][k] != str[j][k]) tmp++; cost[i][j] = cost[j][i] = tmp; } int ans = prim(cost,n); printf("The highest possible quality is 1/%d. ",ans); } }
J - Borg Maze POJ - 3026
题意:迷宫之中的MST
题解:先bfs预处理,之后在进行MST,输入的时候有坑点,wa了好几次

#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<stack> #include<cstdlib> #include <vector> #include <set> #include<queue> using namespace std; #define ll long long #define llu unsigned long long #define INF 0x3f3f3f3f #define PI acos(-1.0) const int maxn = 550; int tree[maxn][maxn],id[maxn][maxn],dis[maxn][maxn],n,m,tot; bool vis[maxn][maxn]; int lowc[maxn],visit[maxn]; char mp[maxn][maxn]; int dx[] = {0,1,0,-1}; int dy[] = {1,0,-1,0}; struct node { int x,y; }; bool check(int x,int y) { if(x >= 1 && x <= n && y >= 1 && y <= m && !vis[x][y] && mp[x][y] != '#') return true; return false; } void bfs(int x,int y) { memset(vis,false,sizeof vis); memset(dis,0,sizeof dis); queue<node>que; node temp; temp.x = x; temp.y = y; que.push(temp); vis[x][y] = true; while(!que.empty()) { temp = que.front(); que.pop(); for(int i=0;i<4;i++) { int nx = temp.x + dx[i]; int ny = temp.y + dy[i]; if(check(nx,ny)) { vis[nx][ny] = true; dis[nx][ny] = dis[temp.x][temp.y] + 1; if(mp[nx][ny] == 'A' || mp[nx][ny] == 'S') tree[id[x][y]][id[nx][ny]] = tree[id[nx][ny]][id[x][y]] = dis[nx][ny]; que.push(node{nx,ny}); } } } } int Prime(int cost[][maxn],int n) { int ans = 0; memset(visit,false,sizeof visit); visit[1] = true; for(int i=2;i<=n;i++) lowc[i] = cost[1][i]; for(int i=2;i<=n;i++) { int minc = INF; int p = -1; for(int j=1;j<=n;j++) if(!visit[j] && minc > lowc[j]) { minc = lowc[j]; p = j; } ans += minc; visit[p] = true; for(int j=1;j<=n;j++) if(!visit[j] && lowc[j] > cost[p][j]) lowc[j] = cost[p][j]; } return ans; } int main() { int t; scanf("%d",&t); while(t--) { int tot = 0; scanf("%d%d ",&m,&n); for(int i=1;i<=n;i++) gets(mp[i] + 1); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(mp[i][j] == 'A' || mp[i][j] == 'S') id[i][j] = ++tot; for(int i=1;i<=tot;i++) for(int j=1;j<=tot;j++) if(i == j) tree[i][j] = 0; else tree[i][j] = INF; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(mp[i][j] == 'A' || mp[i][j] == 'S') bfs(i,j); int ans = Prime(tree,tot); printf("%d ",ans); } }
L - 还是畅通工程 HDU - 1233
题意:直接就是求最小生成树了
题解:板子

#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<stack> #include<cstdlib> #include <vector> #include <set> #include<queue> #include<map> using namespace std; #define ll long long #define llu unsigned long long #define INF 0x3f3f3f3f #define PI acos(-1.0) const int maxn = 1005; const ll mod = 1e9+7; const double eps = 1e-8; int lowc[maxn]; bool vis[maxn]; int Prime(int cost[][maxn],int n) { int ans = 0; memset(vis,false,sizeof vis); vis[0] = true; for(int i=1;i<n;i++) lowc[i] = cost[0][i]; for(int i=1;i<n;i++) { int minc = INF; int p = -1; for(int j=0;j<n;j++) { if(!vis[j] && minc > lowc[j]) { minc = lowc[j]; p = j; } } if(minc == INF) return -1; ans += minc; vis[p] = true; for(int j=0;j<n;j++) if(!vis[j] && lowc[j] > cost[p][j]) lowc[j] = cost[p][j]; } return ans; } int main() { int n; while(scanf("%d",&n) && n) { int cost[maxn][maxn]; memset(cost,0,sizeof cost); for (int i = 0; i < n * (n - 1) / 2; i++) { int a, b, l; scanf("%d%d%d", &a, &b, &l); cost[a-1][b-1] = l; cost[b-1][a-1] = l; } int ans = Prime(cost, n); printf("%d ", ans); } }
N - 畅通工程再续 HDU - 1875
题意:岛之间造桥,只有长度在10~1000才可以造,问最少的花费,花费是桥的长度*100
题解:INF值的判定,INF是长度小于10或者长度大于1000,其余就是Prime的板子

#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<stack> #include<cstdlib> #include <vector> #include <set> #include<queue> #include<map> using namespace std; #define ll long long #define llu unsigned long long #define INF 99999999999.9 #define PI acos(-1.0) const int maxn = 1005; const ll mod = 1e9+7; const double eps = 1e-8; double lowc[maxn]; bool vis[maxn]; double dis(int x1,int y1,int x2,int y2) { double ans = sqrt((double)(x2-x1)*(x2-x1)*1.0 + (y2-y1)*(y2-y1)*1.0); //cout<<ans<<endl; return ans; } bool check(double x) { //cout<<x<<endl; if(x>=10.0 && x<=1000.0) return true; else return false; } double Prime(double cost[][maxn],int n) { double ans = 0; memset(vis,false,sizeof vis); vis[0] = true; for(int i=1;i<n;i++) lowc[i] = cost[0][i]; for(int i=1;i<n;i++) { double minc = INF; int p = -1; for(int j=0;j<n;j++) { if(!vis[j] && minc > lowc[j]) { minc = lowc[j]; p = j; } } if(minc == INF) return -1; ans += minc; vis[p] = true; for(int j=0;j<n;j++) if(!vis[j] && lowc[j] > cost[p][j]) lowc[j] = cost[p][j]; } return ans; } int main() { int t; scanf("%d",&t); while(t--) { int n; scanf("%d",&n); int x[maxn]; int y[maxn]; double cost[maxn][maxn]; for(int i=0;i<n;i++) scanf("%d %d",&x[i],&y[i]); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(i == j) { cost[i][j] = 0; continue; } else if(check(dis(x[i],y[i],x[j],y[j]))) { //cout<<dis(x[i], y[i], x[j], y[j])<<endl; cost[i][j] = dis(x[i], y[i], x[j], y[j]); cost[j][i] = dis(x[i], y[i], x[j], y[j]); } else if(!check(dis(x[i],y[i],x[j],y[j]))) cost[i][j] = INF; } } //cout<<cost[0][1]<<endl; double ans = Prime(cost,n); if(ans == -1) puts("oh!"); else printf("%.1f ",ans * 100); } }