BOJ 474. 小妹妹送很多快递
2014-08-02 20:19
225 查看
题意:给出一张图,保证图是连通图。每条路上会有c个敌人。现在需要每个节点向其他的所有节点送信,只有信使的数量大于等于敌人的个数,才能通过该条路。信使会同时出发。问至少需要多少信使,才能完成上述任务。
思路:最小生成树。利用并查集维护图的连通。
并查集多维护的信息:1.连通块的个数,当整个图只有一个连通块时,退出图的构建。
2.该连通块中节点的个数。当两个块相连的时候,需要加上从一个块到另一个块信使的个数。
坑:即使路上没有敌人,仍然需要一个信使去送信。需要在连通块合并时特判。
代码如下:
思路:最小生成树。利用并查集维护图的连通。
并查集多维护的信息:1.连通块的个数,当整个图只有一个连通块时,退出图的构建。
2.该连通块中节点的个数。当两个块相连的时候,需要加上从一个块到另一个块信使的个数。
坑:即使路上没有敌人,仍然需要一个信使去送信。需要在连通块合并时特判。
代码如下:
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; template<class T> inline bool read(T &n){ T x = 0, tmp = 1; char c = getchar(); while ((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar(); if (c == EOF) return false; if (c == '-') c = getchar(), tmp = -1; while (c >= '0' && c <= '9') x *= 10, x += (c - '0'), c = getchar(); n = x*tmp; return true; } template <class T> inline void write(T n) { if (n < 0) { putchar('-'); n = -n; } int len = 0, data[20]; while (n) { data[len++] = n % 10; n /= 10; } if (!len) data[len++] = 0; while (len--) putchar(data[len] + 48); } struct edge{ int u,v,cost; bool operator < (const edge & a) const{ return cost < a.cost; } }; const int MAX = 101000; int N,T,M; edge G[MAX]; long long ans; struct DisjointSet{ static const int MAX = 10010; int father[MAX], rank[MAX],cnt,sum[MAX]; void clear(int n){ cnt = n; memset(rank,0,sizeof(int) * (n + 1)); for(int i = 1; i <= n; ++i) father[i] = i,sum[i] = 1; } int find(int x){ return x = x == father[x] ? x : find(father[x]); } void merge(edge e){ int x= e.u, y = e.v; x = find(x),y = find(y); if(x != y){ cnt--; if(e.cost == 0) ans += 2 * sum[x] * sum[y]; else ans += 2 * sum[x] * sum[y] * e.cost; if(rank[x] > rank[y]){ father[y] = x; sum[x] += sum[y]; } else{ father[x] = y; sum[y] += sum[x]; if(rank[x] == rank[y]) rank[y]++; } } } }; DisjointSet s; int main(void) { read(T); while(T--){ read(N),read(M); s.clear(N); ans = 0; for(int i = 0 ; i < M; ++i) read(G[i].u),read(G[i].v),read(G[i].cost); sort(G,G + M); for(int i = 0 ; i < M; ++i){ if(s.cnt == 1) break; else if(s.find(G[i].u) != s.find(G[i].v)){ s.merge(G[i]); } } printf("%lld\n",ans); } return 0; }
相关文章推荐
- BOJ 468. 小妹妹送快递
- BOJ 489 小妹妹划船
- 后缀数组模板-boj477.新来的小妹妹 & boj477. 田田背课文
- boj489. 小妹妹去划船
- boj488. 小妹妹个数-素数个数题(打表...)
- boj478. 小妹妹采蘑菇-概率
- BOJ 477. 新来的小妹妹
- BOJ 488 小妹妹个数
- BOJ 478 小妹妹采蘑菇
- 这几天关心加密的人很多
- 快递查询--爬虫,引入requests包和json包--类的形式版本
- 聊天室里发生了很多事情...
- 手机网页在弹出输入法时候挡住输入框?网上找了很多很多 终于找到一个真真可以用的了~
- 今天看了很多大师级人物的简历
- 【快递物流数据中的手机号码应该如何解密?】
- 问题还是很多
- 1062. Talent and Virtue (25) 大量输入输出 scanf printf会比cin cout 省很多时间
- 微软很多很好的。NET 2。0教学视频
- php 快递100接口
- 如果你想学好C#!就一定要看这个!对你很多帮助!