Connect the Cities

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 16070    Accepted Submission(s): 4177

Problem Description
In 2100, since the sea level rise, most of the cities disappear.
Though some survived cities are still connected with others, but most of
them become disconnected. The government wants to build some roads to
connect all of these cities again, but they don’t want to take too much
money.  
 
Input
The first line contains the number of test cases.
Each
test case starts with three integers: n, m and k. n (3 <= n
<=500) stands for the number of survived cities, m (0 <= m <=
25000) stands for the number of roads you can choose to connect the
cities and k (0 <= k <= 100) stands for the number of still
connected cities.
To make it easy, the cities are signed from 1 to n.
Then follow m lines, each contains three integers p, q and c (0 <= c <= 1000), means it takes c to connect p and q.
Then
follow k lines, each line starts with an integer t (2 <= t <= n)
stands for the number of this connected cities. Then t integers follow
stands for the id of these cities.
 
Output
For each case, output the least money you need to take, if it’s impossible, just output -1.
 
Sample Input
1
6 4 3
1 4 2
2 6 1
2 3 5
3 4 33
2 1 2
2 1 3
3 4 5 6
 
Sample Output
1
 
题意:有n个城市,可以修其中的m条道路,然后还有k行,每一行有t个城市,这t个城市都已经连通。
题解:开始以为是普通的并查集,结果死活TLE,用了启发式合并才AC。而且就像很多人的题解里面说的用C++ AC不了。
启发式合并:启发式合并是为了解决合并过程中树退化成链的情况,用dep[i]表示根为i的树的最大深度,合并ra和rb时,采用最大深度小的向最大深度大的进行合 并,如果两棵树的最大深度一样,则随便选择一个作为根,并且将根的最大深度dep自增1,这样做的好处是在n次操作后,任何一棵集合树的最大深度都不会超过log(n),所以使得查找的复杂度降为O( log(n) )。
#include <stdio.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int N = ;
const int M = ;
struct Edge
{
int s,e,len;
} edge[M];
int father[N],n,m,k;
int dep[N];
int _find(int x)
{
if(x==father[x])return x;
return _find(father[x]);
}
int cmp(Edge a,Edge b)
{
return a.len<b.len;
}
int kruskal(int m)
{
sort(edge+,edge+m+,cmp);
int cost = ;
for(int i=; i<=m; i++)
{
int x = _find(edge[i].s);
int y = _find(edge[i].e);
if(x!=y)
{
if(dep[x]==dep[y])
{
father[x] = y;
dep[y]++;
}
else if(dep[x]<dep[y])
{
father[x] = y;
}
else
{
father[y]=x;
}
cost += edge[i].len;
}
}
return cost;
}
int main()
{
int tcase;
scanf("%d",&tcase);
while(tcase--)
{
scanf("%d%d%d",&n,&m,&k);
for(int i=; i<=n; i++)
{
father[i] = i;
dep[i] =;
}
for(int i=; i<=m; i++)
{
scanf("%d%d%d",&edge[i].s,&edge[i].e,&edge[i].len);
}
while(k--)
{
int t,a;
scanf("%d%d",&t,&a);
t--;
while(t--)
{
int b;
scanf("%d",&b);
int x = _find(a);
int y = _find(b);
if(x!=y)
{
if(dep[x]==dep[y])
{
father[x] = y;
dep[y]++;
}
else if(dep[x]<dep[y])
{
father[x] = y;
}
else
{
father[y]=x;
}
}
}
}
int ans = ;
int cost = kruskal(m);
for(int i=; i<=n; i++)
{
if(father[i]==i) ans++;
}
if(ans==)printf("%d\n",cost);
else printf("-1\n");
}
}
 

最新文章

  1. [nRF51822] 15、穿戴式设备上电量检测装置的设计及细节技术点(偏专业硬件文章)
  2. 上传图片shell绕过过滤的几种方法
  3. Centos 6.5 rsync+inotify 两台服务器文件实时同步
  4. JS魔法堂:再识IE的内存泄露
  5. UML类图之类与类的关系
  6. iframe 根据加载内容调整高度
  7. MPlayer-ww 增加边看边剪切功能
  8. linux第4天 shell socket
  9. javascript 金额格式化
  10. offsetWidth、offsetleft 等图文详解
  11. C#程序设计基础——常量
  12. PlugNT CMS v4.6.3 调用文章上一页和下一页及点击数加1
  13. git版本控制工具
  14. BZOJ1800:fly 飞行棋 (双指针 组合数)
  15. springboot系列十二、springboot集成RestTemplate及常见用法
  16. c++ 远程连接局域网内 数据库,并进行操作
  17. Renesas M16C/6X -- Simple PWM Signal Generation Using DMA
  18. Win8交互UX——用于 Windows 的触摸交互
  19. [转] pom.xml 配置详解
  20. HTML: &lt; 和 &gt; 是何方神圣

热门文章

  1. 算法学习记录-图——应用之关键路径(Critical Path)
  2. Android stadio 工具使用
  3. adb 显示手机分辨率
  4. Java-多线程与单例
  5. cycling -avoid the vicious cycle
  6. Block那些事儿
  7. 《Cracking the Coding Interview》——第4章:树和图——题目9
  8. js获取可编辑区域光标位置
  9. web自动化测试,定位不到元素的原因及解决方案(持续更新中2018年9月29日)
  10. JavaWeb笔记(八)JQuery