最小生成树 2016.7.20
2016-06-07 15:24
351 查看
1、UVa 10048 Audiophobia
参考:http://blog.csdn.net/shuangde800/article/details/7985085题意:
c1到c2的每条路径的声强为这条路径所包含的边的最大权值
求c1到c2的声强最小的一条路径的声强
解题思路:
模拟kruskal的过程
先将所有的边按权值递增进行排序,再一条边一条边的加
每加入一次边,就去判断需要查询的那条路径的起点和终点是否在同一个集合里
若在同一个集合里了,那么那条路径中的最大值便是当前加入的这条边的权值,且这条路径是声强最小的一个
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; const int INF = 0x3f3f3f3f; int C, S, Q; struct Node { int s, e; int val; }; struct Query { int s, e; }; int pre[110]; Node node[1010]; Query query[10010]; int ans[10010]; bool vis[10010]; int Rank[110]; int cmp_num(const void* a, const void* b); int Find_Root(int x); int main() { int Case = 0; while (scanf("%d%d%d", &C, &S, &Q) != EOF && !(C == 0 && S == 0 && Q == 0)) { for (int i = 0; i < S; ++i) { scanf("%d%d%d", &node[i].s, &node[i].e, &node[i].val); } for (int i = 0; i < Q; ++i) { scanf("%d%d", &query[i].s, &query[i].e); } ++Case; if (Case > 1) { printf("\n"); } printf("Case #%d\n", Case); for (int i = 1; i <= C; ++i) { pre[i] = i; Rank[i] = 0; } qsort(node, S, sizeof(node[0]), cmp_num); memset(ans, -1, sizeof(ans)); memset(vis, false, sizeof(vis)); for (int i = 0; i < S; ++i) { int nx = Find_Root(node[i].s); int ny = Find_Root(node[i].e); if (nx != ny) { if (Rank[nx] > Rank[ny]) { pre[ny] = nx; } else { if (Rank[nx] == Rank[ny]) { ++Rank[ny]; } pre[nx] = ny; } for (int j = 0; j < Q; ++j) { if (!vis[j]) { int qx = Find_Root(query[j].s); int qy = Find_Root(query[j].e); if (qx == qy) { vis[j] = true; ans[j] = node[i].val; } } } } } for (int i = 0; i < Q; ++i) { if (ans[i] != -1) { printf("%d\n", ans[i]); } else { printf("no path\n"); } } } return 0; } int cmp_num(const void* a, const void* b) { Node* x = (Node*)a; Node* y = (Node*)b; return (x->val - y->val) > 0 ? 1 : -1; } int Find_Root(int x) { int r = x; while (pre[r] != r) { r = pre[r]; } while (pre[x] != r) { int t = pre[x]; pre[x] = r; x = t; } return r; }
2、POJ 1258 Agri-Net
Prim#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <queue> #include <vector> #include <stack> #include <map> #include <cmath> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef unsigned int uint; const int mod = 1e9 + 7; const int INF = 0x7fffffff; const int maxn = 100 + 10; int Graph[maxn][maxn]; int lowcost[maxn]; bool vis[maxn]; int N; int Prim(void); int main() { while (scanf("%d", &N) != EOF) { for (int i = 1; i <= N; ++i) { for (int j = 1; j <= N; ++j) { scanf("%d", &Graph[i][j]); } } printf("%d\n", Prim()); } return 0; } int Prim(void) { memset(vis, false, sizeof(vis)); int sum = 0; for (int i = 2; i <= N; ++i) { lowcost[i] = Graph[1][i]; } for (int i = 0; i < N-1; ++i) { int Min = INF; int t; for (int j = 2; j <= N; ++j) { if (!vis[j] && lowcost[j] < Min) { Min = lowcost[j]; t = j; } } if (Min == INF) { break; } vis[t] = true; sum += lowcost[t]; for (int j = 2; j <= N; ++j) { if (!vis[j] && lowcost[j] > Graph[t][j]) { lowcost[j] = Graph[t][j]; } } } return sum; }
3、HDU 1102 Constructing Roads
Prim#include <iostream> #include <cstring> #include <cstdio> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 100 + 5; int Map[maxn][maxn]; int lowcost[maxn]; bool vis[maxn]; int N; int sum; void Prime(void); int main() { while (cin>>N) { memset(vis, false, sizeof(vis)); for (int i=1; i<=N; ++i) { for (int j=1; j<=N; ++j) { cin>>Map[i][j]; } } int Q; cin>>Q; int a, b; for (int i=0; i<Q; ++i) { cin>>a>>b; Map[a] = Map[b][a] = 0; } sum = 0; Prime(); cout<<sum<<endl; } return 0; } void Prime(void) { for (int i=2; i<=N; ++i) { lowcost[i] = Map[1][i]; } for (int i=2; i<=N; ++i) { int Min = INF; int t; for (int j=2; j<=N; ++j) { if (!vis[j] && Min > lowcost[j]) { Min = lowcost[j]; t = j; } } if (Min == INF) { break; } sum += Min; vis[t] = true; for (int j=2; j<=N; ++j) { if (!vis[j] && lowcost[j] > Map[t][j]) { lowcost[j] = Map[t][j]; } } } }
[b]4、POJ 1251 Jungle Roads
Prim#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 40; int Map[maxn][maxn]; int lowcost[maxn]; bool vis[maxn]; int n; int sum; void Prime(void); int main() { while (cin>>n && n!=0) { memset(vis, false, sizeof(vis)); for (int i=1; i<=n; ++i) { for (int j=1; j<=n; ++j) { if (i == j) { Map[i][j] = 0; } else { Map[i][j] = INF; } } } char c; int num1, num2; for (int i=0; i<n-1; ++i) { cin>>c>>num1; int s = c - 'A' + 1; for (int j=0; j<num1; ++j) { cin>>c>>num2; int e = c - 'A' + 1; Map[s][e] = Map[e][s] = num2; } } sum = 0; Prime(); cout<<sum<<endl; } return 0; } void Prime(void) { for (int i=1; i<=n; ++i) { lowcost[i] = Map[1][i]; } for (int i=2; i<=n; ++i) { int Min = INF; int t; for (int j=2; j<=n; ++j) { if (!vis[j] && Min > lowcost[j]) { t = j; Min = lowcost[j]; } } if (Min == INF) { break; } sum += Min; vis[t] = true; for (int j=2; j<=n; ++j) { if (!vis[j] && lowcost[j] > Map[t][j]) { lowcost[j] = Map[t][j]; } } } }
5、HDU 5723 Abandoned country
解题思路:http://bestcoder.hdu.edu.cn/blog/2016-multi-university-training-contest-1-solutions-by-hit/
标程:
#include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <vector> using namespace std; #define N 100010 struct node { int u, v, w; node() {} node(int _u, int _v, int _w):u(_u), v(_v), w(_w) {} }; struct Node{ int v,len; Node(){} Node(int _v, int _len):v(_v), len(_len){} }; vector<Node>vet ; vector<node> edge; int n, m, f ; double dp ; int sum ; bool cmp(const node &x, const node &y) { return x.w < y.w; } int find_set(int x) { if (f[x] == x) return x; return f[x] = find_set(f[x]); } long long Kruskal() { sort(edge.begin(), edge.end(), cmp); for (int i = 1; i <= n; i++) f[i] = i; long long ans = 0; for (int i = 0, u, v, w; i < (int)edge.size(); i++) { u = edge[i].u, v = edge[i].v, w = edge[i].w; u = find_set(u), v = find_set(v); if (u == v) continue; f[u] = v; ans += (long long)w; vet[edge[i].u].push_back(Node(edge[i].v,w)); vet[edge[i].v].push_back(Node(edge[i].u,w)); } return ans; } void dfs(int root,int father) { sum[root] = 1; for(int i = 0;i < (int)vet[root].size();i++) { int son = vet[root][i].v; int len = vet[root][i].len; if(son == father)continue; dfs(son,root); sum[root] += sum[son]; dp[root] += dp[son] + ((double)sum[son] * (n - sum[son])) * len; } } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); int t; scanf("%d",&t); while(t--) { scanf("%d%d", &n, &m); edge.clear(); for (int i = 0, a, b, c; i < m; i++) { scanf("%d%d%d", &a, &b, &c); edge.push_back(node(a, b, c)); } for(int i = 1;i <= n;i++)vet[i].clear(); memset(sum,0,sizeof(sum)); memset(dp,0,sizeof(dp)); long long ans = Kruskal(); dfs(1,0); long long s = (long long)n * (n - 1) / 2; printf("%I64d %.2f\n",ans,dp[1] / (double)s); } return 0; }
看官方的标程和解题思路看了一上午才敲出来,刚开始也想到统计每条边用过的次数乘以边权然后加起来,最后除以总数,但是做法完全错误
第一次多校赛一题未出,为什么会有我这么菜的人...%%%大牛们
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <algorithm> #include <queue> #include <vector> #include <stack> #include <map> #include <cmath> #include <cctype> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef unsigned int uint; const ull mod = 1e9 + 7; const int INF = 0x7fffffff; const int maxn = 1e5 + 10; int n, m; struct Node { int s, e; int dis; }; struct V { int key, dis; }; vector<V> v[maxn]; Node node[1000010]; int pre[maxn]; int sum[maxn]; double ans[maxn]; int Find_Root(int x); bool cmp(Node a, Node b); void dfs(int root, int father); int main() { #ifdef __AiR_H freopen("in.txt", "r", stdin); #endif // __AiR_H int T; scanf("%d", &T); while (T--) { memset(sum, 0, sizeof(sum)); memset(ans, 0, sizeof(ans)); scanf("%d%d", &n, &m); for (int i = 1; i <= n; ++i) { v[i].clear(); } for (int i = 1; i <= n; ++i) { pre[i] = i; } for (int i = 0; i < m; ++i) { scanf("%d%d%d", &node[i].s, &node[i].e, &node[i].dis); } sort(node, node+m, cmp); ull Min = 0; for (int i = 0; i < m; ++i) { int ra = Find_Root(node[i].s), rb = Find_Root(node[i].e); if (ra != rb) { Min += node[i].dis; pre[ra] = rb; V t; t.key = node[i].e, t.dis = node[i].dis; v[node[i].s].push_back(t); t.key = node[i].s; v[node[i].e].push_back(t); } } dfs(1, 0); ull t = (ull)n * (n-1) / 2; printf("%I64d %.2f\n", Min, ans[1] / (1.0 * t)); } return 0; } void dfs(int root, int father) { sum[root] = 1; for (int i = 0; i < (int)v[root].size(); ++i) { int son = v[root][i].key; int dis = v[root][i].dis; if (son != father) { dfs(son, root); sum[root] += sum[son]; ans[root] += ans[son] + 1.0 * sum[son] * (n - sum[son]) * dis; } } } int Find_Root(int x) { int r = x; while (pre[r] != r) { r = pre[r]; } while (pre[x] != r) { int t = pre[x]; pre[x] = r; x = t; } return r; } bool cmp(Node a, Node b) { return (a.dis < b.dis); }
相关文章推荐
- 汉字 字符的区别
- 如何获取手机上所有的音乐文件
- springMVC 的两种文件上传方式
- POST 传参
- 实体框架Entity Framework(EF) 官方资料入口
- 比较牛逼的答题卡扫描算法
- SESSION冲突
- 图像配准简介
- Android-XmlPullParser解析XML
- 查看CPU等参数配置
- 【官小飞】博主文章转载-文件上传和下载
- ios9和ios10的新特性
- AngularJS 实现的输入自动完成补充功能
- 调用外部js方法
- 网络服务器搭建的那些事(PV QPS Throughput)
- iOS app 后台运行利用本地推送处理蓝牙设备通讯指令
- 一些关于机器视觉的概念(转)
- C++实现插入排序
- Java对于Cookie的操作详解
- CMFCStatusBar 状态栏字体颜色为灰色