Codeforces 400D Dima and Bacteria 【并查集 + 最短路】
2016-03-21 23:56
417 查看
题目链接:Codeforces 400D Dima and Bacteria
题意:有n个点m条边的无向带权图。我们假设有k个集合,集合i元素个数记为c[i],集合里面任意两点间距离为0。问我们的假设是否成立,成立的话输出k∗k矩阵代表集合间的最短路。
注意有一个重要信息——
集合k里面的点编号从∑k−1i=1c[i]to∑ki=1c[i],这样这道题就是大水题了。
思路:用个并查集维护就好了,最后跑一次floyd就OK了。
AC代码:
题意:有n个点m条边的无向带权图。我们假设有k个集合,集合i元素个数记为c[i],集合里面任意两点间距离为0。问我们的假设是否成立,成立的话输出k∗k矩阵代表集合间的最短路。
注意有一个重要信息——
集合k里面的点编号从∑k−1i=1c[i]to∑ki=1c[i],这样这道题就是大水题了。
思路:用个并查集维护就好了,最后跑一次floyd就OK了。
AC代码:
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <map> #include <stack> #define PI acos(-1.0) #define CLR(a, b) memset(a, (b), sizeof(a)) #define fi first #define se second #define ll o<<1 #define rr o<<1|1 using namespace std; typedef long long LL; typedef pair<int, int> pii; const int MAXN = 1e5 + 10; const int pN = 1e6;// <= 10^7 const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; void add(LL &x, LL y) { x += y; x %= MOD; } int c[510]; int u[MAXN], v[MAXN], w[MAXN]; int father[MAXN], id[MAXN]; int Map[510][510]; int Find(int p) { int t, child = p; while(p != father[p]) p = father[p]; while(child != p) {t = father[p]; father[child] = p; child = t;} return p; } void Merge(int x, int y) { int fx = Find(x); int fy = Find(y); if(fx != fy) father[fx] = fy; } int main() { int n, m, k; cin >> n >> m >> k; c[0] = 0; for(int i = 1; i <= k; i++) { cin >> c[i]; c[i] += c[i-1]; } for(int i = 0; i < m; i++) { cin >> u[i] >> v[i] >> w[i]; } for(int i = 1; i <= n; i++) { father[i] = i; } for(int i = 0; i < m; i++) { if(w[i] == 0) { Merge(u[i], v[i]); } } bool flag = true; c[0] = 0; for(int i = 1; i <= k; i++) { int root = Find(c[i-1]+1); for(int j = c[i-1]+1; j <= c[i]; j++) { if(Find(j) != root) { flag = false; break; } id[j] = i; } if(!flag) break; } if(!flag) { cout << "No" << endl; return 0; } cout << "Yes" << endl; for(int i = 1; i <= k; i++) { for(int j = 1; j <= k; j++) { if(i == j) Map[i][j] = 0; else Map[i][j] = INF; } } for(int i = 0; i < m; i++) { int s = id[u[i]]; int t = id[v[i]]; Map[s][t] = Map[t][s] = min(Map[s][t], w[i]); } for(int p = 1; p <= k; p++) { for(int i = 1; i <= k; i++) { for(int j = 1; j <= k; j++) { Map[i][j] = min(Map[i][j], Map[i][p] + Map[p][j]); } } } for(int i = 1; i <= k; i++) { for(int j = 1; j <= k; j++) { if(j > 1) cout << " "; if(Map[i][j] == INF) cout << -1; else cout << Map[i][j]; } cout << endl; } return 0; }
相关文章推荐
- Android EditText 不能输入 手机输入法自带 Emoji 表情,为EditText 添加输入限制
- 优秀开源项目网址收藏
- c语言:单链表的实现(一) 创建,插入,删除,查找
- Android之状态栏通知Notification、NotificationManager详解
- C语言习题 计算该日在本年中是第几天
- Oracle新建数据库和用户及表空间
- 40个Java多线程问题总结
- Weblogic整合的一些利用方法20160321
- Android 高清加载巨图方案 拒绝压缩图片
- IOS学习 动画和绘画:UIView基础动画
- AsyncTask源码分析
- 技术积累--常用的文本分类的特征选择算法
- 又是一年春天里
- Maven新建项目更改默认JDK版本
- 小马哥-----高仿机修复摄像头实例说明 其他机型可借鉴
- PB 数据窗口语法解释
- Spring源码之ApplicationContext(十)过程刷新
- ksh
- Ibatis的类型处理器TypeHandler解析
- DHCP的8类报文抓包以及option详解