题解 P4185 【[USACO18JAN]MooTube】

蔡俊黠

2018-03-24 20:48:43

Solution

哇没想到我也能做提高+的题好开心 一开始很简单粗暴地想到了邻接矩阵,做到10分才发觉这么高大上的题目你用这个方法来做是不是大傻X 看了大牛 elijahqi 的题解就想明白了原来是并查集啊~~哈哈哈~~ 蒟蒻的第一篇题解就你了哈哈 思路: 1. 在并查集的基础上加一点料,并查集原来是有边就把它连的两个点合并嘛,在这里我们吧、加一个条件,要>=k即符合条件的边才给它合并,这样的话这个连通块中所有的点都符合条件啦 2. 但是如果每次询问都重新合并一次的话会超时啊孩纸,所以我们用到两个快排,把每条边从大到小排 ,再把 询问的k从大到小排,先做最大的k,把符合条件的点合并后(不要忘记统计结点数,这个才是我们想要的嘛),那么下一个k肯定比这个小啦(排序了嘛),那么符合大k的点肯定符合小k的点啦,那么就不用再重复合并啦,做到第i个k,这个连通块中的结点就符合条件啦 ~~阿拉拉拉~~ emmm好像就这些把,我能理解的想必大神们都能理解嘻嘻 如果我说得有什么不对或遗漏的欢迎评论哦 不BB了上题解 ```cpp #include<iostream> #include<cstdio> #include<algorithm> using namespace std; int j=1,n,q,number[110000],father[110000],ans[110000]; struct kind{ int start; int end; int w; }bian[110000]; struct kind2 { int k; int v; int id; }ask[110000]; int cmp(kind x,kind y){ return x.w>y.w; } int cmp2(kind2 x,kind2 y){ return x.k>y.k; } int getfather(int x) //寻找x的父节点 { if (father[x]!=x) father[x]=getfather(father[x]); return father[x]; } void onion(int x,int y) { x=getfather(x); y=getfather(y); if (x!=y) { father[x]=y; //合并父节点就把它们合并啦啦啦 number[y]+=number[x]; //父亲又多了几个儿子哈哈 } } int main() { cin>>n>>q; for (int i=1;i<=n;i++) { father[i]=i; number[i]=1; //number[]统计连通块中的结点数量 } for (int i=1;i<n;i++) cin>>bian[i].start>>bian[i].end>>bian[i].w; //读入起始点,到达点,边(连自己都觉得幼稚的数组bian[]) for (int i=1;i<=q;i++) { cin>>ask[i].k>>ask[i].v; ask[i].id=i; } //“离线”操作 ,因为后面还要对询问中的k进行排序(“离线”是指读入完后再操作,“在线”是指边读入边操作) sort(bian+1,bian+n+1,cmp); //对bian[]数组进行快排,把每条边的长度从大到小排,方便后面将>=k的边连接的点进行合并 sort(ask+1,ask+1+q,cmp2); //对ask[]询问数组进行快排,把询问的k从大到小排, for (int i=1;i<=q;i++) //对每个个询问进行操作 { while (j<n&&bian[j].w>=ask[i].k) //也可以用for语句代替,不过要把bian[j].w>=ask[i].k写在 for()括号里,避免多余的操作,不然会TLE的啊 //把每条>=k的边连接的点进行合并,即将符合条件的点都拉进这个连通块,那么这个连通块中所有的点都符合条件 //注意:变量j的声明一定要放在外面啊,不然会TLE,为什么呢,因为我们是把k从大做到小,k=4这个连通块里的结点肯定也符合k=3的这个条件,所以就不必要做重复的结合啦 { onion(bian[j].start,bian[j].end); j++; } ans[ask[i].id]=number[getfather(ask[i].v)]; //ans[]就是要输出的东西啦,要保证原来的输入对应输出,就需要ans[ask.id]这个东西,找到v点的父节点,那么符合条件的节点数就在number[]里面啦啦啦 } for (int i=1;i<=q;i++) cout<<ans[i]-1<<endl; //去掉自己一个结点后输出 return 0; //Yeah~~ } ```