CSU 1845:Sensor Network. Link Cut Tree 解法(2010 Southwestern European Regional Contest)

来源:互联网 发布:农村淘宝视频 编辑:程序博客网 时间:2024/05/17 19:19

1845: Sensor network       Time Limit: 20 Sec     Memory Limit: 128 Mb     Submitted: 15     Solved: 9    


Description

  In response to a request by the SWERC 2010 problem-setting team, a sensor network has just been installed in the headquarters. The organizing committee has put in the problem-setters the disproportionate fear of suffering a leak of classified information about the problems.

  Nevertheless, in the rush they forgot to think about the electricity network needed to make the sensors work. Because of this, the security system is currently not working, but we need to justify the great amount of resources invested in it, so the installation must be ready before the end of the contest. Hence you are now asked to elaborate a program which will help the electrician in his duty.

  Since the organizing committee spared no expense, they ordered the sensors from a prestigious company.Every sensor is handcrafted and a number is written on each of them, whose meaning is the recommended voltage that should be applied to it for correct operation. They can be used under higher voltages, with an increasing risk of failure, but never with a voltage below the recommended one. The electrician gazed open-mouthed at the sensors when they were given to him: nearly all of them had different recommended voltages! The sensors were installed in the building in such a way that each of them controls exactly two doors and every door is controlled by at least one sensor. Now is the time for the electrician to supply power to the sensors. He faces the following constraints:

  • Fortunately, there is no need to activate all sensors. However, we will require that the subset of sensors chosen to be on satisfy that every door is controlled by, at least, one sensor in the subset. 
  • Electricity is to be supplied to one of the active sensors, and then distributed to the others with wires.In order not to waste wires, they can only be installed by connecting a pair of neighboring active sensors (by "neighbouring" we mean that some door is controlled by both of them). Since we must supply energy to every active sensor, not every subset of sensors is suitable as the chosen subset of working sensors. 
  • Because of the above, all of the sensors will be supplied the same voltage, which cannot be below the corresponding recommended voltages.

    For simplicity, we will refer to a subset of sensors satisfying the first two constraints above as an admissible subset. The network is designed so that the set of all sensors is always admissible, but we would like to take a possibly smaller subset so as to minimize the margin, designed as the maximum of the differences, in absolute value, between the numbers written on each pair of sensors in the subset. (This is to keep the chances of failure to a minimum).

  The electrician could not solve the task of finding the admissible subset of the set of sensors for which the margin is minimum. Therefore, the electrical installation is still missing. Today, we ask you to write a program to find out the answer, given a sensor network and the recommended voltage for each of the sensors.

Input

  The input consists of several test cases, separated by single blank lines. Each test case begins with a line containing the integer n (2n3502≤n≤350 ), the number of doors in the building. The following line contains another integermm , (n1)mn(n1)/2(n−1)≤m≤n(n−1)/2,the number of sensors in the network. The test case finishes with m lines containing a description of each of the m sensors.The i-th of those lines contains three integers,a(0a(n1)),b(0b(n1)),w(1w215)a(0≤a≤(n−1)),b(0≤b≤(n−1)),w(1≤w≤215),in that order. Integers a and b represent the pair of doors controlled by the i-th sensor, and w its recommended voltage. You can safely assume that there are no two sensors controlling the same two doors.

  The input will finish with a line containing 0.

Output

  For each case, your program should output a line containing the minimum margin of an admissible subset of the sensors.

Sample Input

330 1 2201 2 1202 0 160452 3 801 3 800 1 1802 1 2003 0 1400

Sample Output

4060

        目前为止比得最失败的一场多校赛,所有人的成绩都不好……果然是WF大佬出的题目……

        题目大意:给出很多个点,然后有很多个带权值的边,要求求一棵生成树,使得这棵树中边权值的极差最小,并输出这个极差。

        根据贪心的思想,我们首先要想kruskal那样先对所有边按照边权值来排序,排序之后,连续的几条边如果构成生成树,那么这棵生成树的极差就是备选解。即不用考虑非连续的情况,因为非连续情况一定有比他更优的解。这样,我们只需要枚举这个连续的区间了。我们设定一个集合f,边按照从小到大的顺序一次检索,如果该边连接的两点不连通,即不构成环,那么我们连这条边,并把边加入集合f。如果两点已经连通,那么,删除两点路径上边权最小的边,然后再连上这条边。当集合的大小为n-1时,说明已经构成了一棵生成树,那么我们把备选解与最终解进行比较即可。

        现在,问题就转化为了需要我们不断的连边、删边,并判断连通性。显然,我们想到了用Link Cut Tree O(MlogN)这种数据结构去执行这种操作,当然你也可以用树链剖分 O(MlogN)或者直接暴力dfs O(mn)。不过,既然是题解(补题),我们就要做到极致,顺便巩固一下Link Cut Tree。

        由于Link Cut Tree对边权的维护和判断比较麻烦,所以我们可以对每一条边对应新建立一个点,然后把所有边权赋到相应点的点权中,删连边时也以该点为桥梁。这样我们就可以对每一条链维护链中边权最大的边。在判断连通性时直接用findroot判断是否在同根树中,然后连边直接Link,删边直接Cut。剩下的就是直接打模板就行了,(对自己写的Link Cut Tree 的模板,我还是很满意的),代码如下:

#include<bits/stdc++.h>#define MAX_V 70000using namespace std;struct Node{int l,r,fa,min,num;bool rev;} tree[MAX_V];struct Edge{    int x,y,w;} g[70000];bool root[MAX_V];deque<int> sta;vector<int> q;int n,m;inline bool get(int x){return tree[tree[x].fa].r==x;}inline void pushup(int x){if (x){tree[x].min=tree[x].num;if (tree[x].l) tree[x].min=min(tree[x].min,tree[tree[x].l].min);if (tree[x].r) tree[x].min=min(tree[x].min,tree[tree[x].r].min);}}inline void reverse(int x){if (x){swap(tree[x].l,tree[x].r);tree[x].rev^=1;}}inline void pushdown(int x){if ((x)&&(tree[x].rev)){reverse(tree[x].l);reverse(tree[x].r);tree[x].rev=0;}}inline void rotate(int x){int fa=tree[x].fa,grand=tree[fa].fa;if (get(x)){tree[fa].r=tree[x].l;tree[tree[x].l].fa=fa;tree[x].l=fa;} else{tree[fa].l=tree[x].r;tree[tree[x].r].fa=fa;tree[x].r=fa;}tree[x].fa=grand;tree[fa].fa=x;if (root[fa]) root[x]=1,root[fa]=0;else if (grand){if (tree[grand].l==fa) tree[grand].l=x;else if (tree[grand].r==fa) tree[grand].r=x;}pushup(fa);}inline void splay(int x){int i=x; sta.clear();for(;!root[i];i=tree[i].fa)sta.push_back(i);sta.push_back(i);while (!sta.empty()){pushdown(sta.back());sta.pop_back();}while (!root[x]){if (!root[tree[x].fa]){if (get(x)==get(tree[x].fa)) rotate(tree[x].fa);                        else rotate(x);}rotate(x);}pushup(x);}inline void access(int x){int y=0;while (x){splay(x);root[y]=0;root[tree[x].r]=1;tree[x].r=y;pushup(x);y=x,x=tree[x].fa;}}inline void beroot(int x){access(x);splay(x);reverse(x);}inline int findroot(int x){while (tree[x].fa) x=tree[x].fa;return x;}inline void link(int x,int y){beroot(x);tree[x].fa=y;}inline void cut(int x,int y){beroot(x);access(y);splay(y);tree[tree[y].l].fa=0;root[tree[y].l]=1;tree[y].l=0;pushup(y);}inline void del(int x,int y){beroot(x);access(y);splay(y);int i=tree[y].min;cut(g[i].x,i+n+1);cut(i+n+1,g[i].y);vector<int>::iterator it=lower_bound(q.begin(),q.end(),i);q.erase(it);}inline bool cmp(Edge a,Edge b){    return a.w<b.w;}int main(){    while (1)    {        scanf("%d",&n);        if (n==0) return 0;        scanf("%d",&m);        for(int i=0;i<m;i++)        {        scanf("%d%d%d",&g[i].x,&g[i].y,&g[i].w);        g[i].x++; g[i].y++;}        int ans=1e9;        for(int i=0;i<=n+m+1;i++)        {        tree[i].num=tree[i].min=1e6;root[i]=1;        tree[i].l=tree[i].r=tree[i].fa=0;}        sort(g,g+m,cmp); q.clear();        for(int i=0;i<m;i++)        {            if (findroot(g[i].x)==findroot(g[i].y)) del(g[i].x,g[i].y);            link(g[i].x,i+n+1);            link(i+n+1,g[i].y);            tree[i+n+1].num=tree[i+n+1].min=i;            q.push_back(i);            if (q.size()==n-1) ans=min(ans,g[i].w-g[q[0]].w);        }        printf("%d\n",ans);    }    return 0;}


0 0
原创粉丝点击