hdu 4313 - Matrix(最小生成树,并查集)
2013-10-03 20:44
513 查看
题目:
N个点N-1条无向边,K个数,要求去掉一些边,使得这K个数相互不可达,求去掉的边的权值和的最小值
思路:
这K个数不能相互到达,说明这k个数分别属于不同的集合,我们把可以放进同一集合的数作为同一集合,不能放进的,则把这条边舍弃。集合自然想到用并查集。要找最小值,我们可以把所有边按权值从大到小排序,顺序寻找,找到不能放进的则跳过,res+=w,能放进的则进行合并(由于我们其实是找的能够合并的边,只是顺路找不能合并的,所以从大到小排序,大的先合并了,剩余的不能合并的就小了) , 取权值构造图,自然想到最小生成树。
代码:
克鲁斯卡尔算法:
Matrix
题意:N个点N-1条无向边,K个数,要求去掉一些边,使得这K个数相互不可达,求去掉的边的权值和的最小值
思路:
这K个数不能相互到达,说明这k个数分别属于不同的集合,我们把可以放进同一集合的数作为同一集合,不能放进的,则把这条边舍弃。集合自然想到用并查集。要找最小值,我们可以把所有边按权值从大到小排序,顺序寻找,找到不能放进的则跳过,res+=w,能放进的则进行合并(由于我们其实是找的能够合并的边,只是顺路找不能合并的,所以从大到小排序,大的先合并了,剩余的不能合并的就小了) , 取权值构造图,自然想到最小生成树。
代码:
克鲁斯卡尔算法:
//#pragma comment(linker, "/STACK:102400000,102400000") #include "iostream" #include "cstring" #include "algorithm" #include "cmath" #include "cstdio" #include "sstream" #include "queue" #include "vector" #include "string" #include "stack" #include "cstdlib" #include "deque" #include "fstream" #include "map" using namespace std; typedef long long LL; const int INF = 522133279; const int MAXN = 1000000+100; #define eps 1e-14 const int mod = 100000007; int set[100000+100]; struct edge { int s; int e; int w; bool operator <(const edge&b)const { return w > b.w; } } e[100000+100]; int des[100000+100]; //1 - 是剔除点 0 - 非剔除点 int n,k; int find(int x) { return set[x] != x ? set[x] = find(set[x]) : x; } int merger(int x , int y) { return ((x = find(x)) != (y = find(y))) && (set[x]=y); } LL ckru(int n) { sort(e,e+n-1); LL res = 0; for(int i = 0 ; i < n-1 ; i++) { int u = find(e[i].e); int v = find(e[i].s); if(!des[u] || !des[v]) //如果不是两个都是剔除点,则合并,注意正常点应该被剔除点合并 { if(des[v]) merger(u,v); else if(des[u]) merger(v,u); else merger(u,v); } else if(des[u] && des[v]) //如果两个都是剔除点,那么这条边不应该被加进去,也就是它应该被销毁 res += e[i].w; } return res; } int main() { //freopen("in","r",stdin); //freopen("out","w",stdout); int t; scanf("%d" , &t); while(t--) { memset(des,0,sizeof(des)); scanf("%d%d",&n,&k); for(int i = 0 ; i <= n ; i++) set[i]=i; for(int i = 0 ; i < n-1 ; i++) scanf("%d%d%d" , &e[i].s,&e[i].e,&e[i].w); for(int i = 0 ; i < k ; i++) { int tmp; scanf("%d" , &tmp); des[tmp]=1; } printf("%I64d\n", ckru(n)); } return 0; }
相关文章推荐
- HDU 4313 Matrix(并查集|最小生成树变种)
- hdu 4313 Matrix (最小生成树krusual)
- HDU 4313 Matrix (最小生成树)
- HDU-4313 Matrix 最小生成树,集合划分
- HDU-1863(最小生成树+并查集判断是否连通)
- hdu 1233(还是畅通工程)(prime算法,克鲁斯卡尔算法)(并查集,最小生成树)
- hdu 2682 Tree 最小生成树 (并查集)
- HDU 1233.还是畅通工程【最小生成树 kruskal算法(并查集)+prim算法】【1月8】
- HDU 4313 Matrix (贪心+并查集)
- HDU 3371 Connect the Cities (最小生成树 并查集+克鲁斯卡尔)
- HDU 4463 最小生成树 并查集
- hdu 1233(还是畅通project)(prime算法,克鲁斯卡尔算法)(并查集,最小生成树)
- HDU 4313 Matrix(并查集/破坏边使得k个点两两不连通的最少代价)
- HDU 1232(最小生成树;并查集)
- 并查集--HDU - 4313 Matrix
- HDU 4313 Matrix(贪心+并查集)
- hdu 1272 小希的迷宫(并查集 最小生成树)
- HDU 1233(最小生成树,并查集)
- hdu 1233 还是畅通工程 最小生成树Kruskal算法(并查集)
- HDU1879 并查集和最小生成树