poj1061Jungle Roads
题意:就是求最小生成树所有边之和。是到最小生成树的水题,就是存图委实有点恶心。
1.Kruskal Algorithm
把所有边从小到大排序,在加入边的过程中,1.判断是否所有点已经进入树中,如果是,则停止。2.判断对应的点是否已经加入集合,如果是则不加入该点。最后计算边之和。
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
const int maxn = 26;
int n;
int cnt;
struct st {
char a;
char b;
int c;
}edge[maxn*maxn];
int f[maxn];
int cmp(const void *a,const void *b) {
struct st *c = (st*)a;
struct st *d = (st*)b;
return c->c-d->c;
}
int find(int x) {
while(x != f[x]) {
x = f[x];
}
return x;
}
bool Union(int x,int y) {
int a = find(x);
int b = find(y);
if(a != b) {
f[b] = a;
return true;
}
else
return false;
}
int main() {
int str[5];
int str1[5];
int a,b;
while(scanf("%d",&n) != EOF && n) {
getchar();
cnt = 0;
for(int i = 0; i < 26; i++) {
f[i] = i;
}
int count = 0, sum = 0;
for(int i = 1; i <= n-1; i++) {
scanf("%s%d",str,&a);
for(int i = 0; i < a; i++) {
scanf("%s%d",str1,&b);
edge[cnt].a = str[0] - 'A';
edge[cnt].b = str1[0] - 'A';
edge[cnt].c = b;
cnt++;
}
}
qsort(edge,cnt,sizeof(edge[0]),cmp);
for(int i = 0; i < cnt; i++) {
if(count == n-1) break;
if(Union(edge[i].a,edge[i].b)) {
count++;
sum += edge[i].c;
}
}
printf("%d\n",sum);
}
return 0;
}
维护三个数组。
dis:当前该点到集合需要的最小长度
parent:dis边对应的集合中的点,把集合该点记录下来,以记录最小生成树的边
vis:该点是否已在集合中。
松弛的思想来遍历即可
# include <stdio.h>
# include <string.h>
# include <queue>
using namespace std;
const int INF = 0x3f3f3f3f;
int n;
int Map[30][30];
char str[5];
char str1[5];
int dis[30];
int parent[30];
bool vis[30];
int sum;
void spfa() {
memset(vis,0,sizeof(vis));
memset(dis,INF,sizeof(dis));
memset(parent,-1,sizeof(parent));
vis[1] = true;
dis[1] = 0;
queue<int> Q;
Q.push(1);
while(!Q.empty()) {
int v = Q.front();
Q.pop();
for(int i = 2; i <= n; i++) {
if(!vis[i] && dis[i] > Map[i][v]) {
dis[i] = Map[i][v];
parent[i] = v;
}
}
int m = 0x3f3f3f3f, x = 0;
for(int i = 2; i <= n; i++) {
if(!vis[i] && m > dis[i]) {
m = dis[i];
x = i;
}
}
if(x == 0) break;
vis[x] = true;
Q.push(x);
}
}
int main() {
while(scanf("%d",&n) != EOF && n) {
memset(Map,INF,sizeof(Map));
for(int i = 1; i <= n-1; i++) {
int num;
scanf("%s%d",str,&num);
for(int i = 0; i < num; i++) {
int w;
scanf("%s%d",str1,&w);
int a, b, c;
a = str[0] - 'A'+1;
b = str1[0] - 'A'+1;
c = w;
Map[a][b] = Map[b][a] = c;
}
}
sum = 0;
spfa();
for(int i = 2; i <= n; i++) {
int from = parent[i];
if(from != -1)
sum += Map[from][i];
}
printf("%d\n",sum);
}
return 0;
}