(intermediate)最小生成树 UVA 12275 - Sensor network

来源:互联网 发布:鬼影 电影 知乎 编辑:程序博客网 时间:2024/05/16 10:35

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, defined 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 ( 2$ \le$n$ \le$350), the number of doors in the building. The following line contains another integer, m ( n - 1$ \le$m$ \le$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 ( 0$ \le$a$ \le$n - 1), b ( 0$ \le$b$ \le$n - 1) and w ( 1$ \le$w$ \le$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

题意:就是找出一个生成树,使得树里面的最大边减去最小边最小。

思路:看了题解才会。。。太菜了。。。一开始我是枚举最小边,然后找最小瓶颈生成树,但是很明显会超时因为复杂度是O(m^2) ,然后发现w范围在[1,2^15] 然后开始枚举最小边的值,虽然快了不少,但是还是超时。。。最后看题解,原来比较好的作法是,一开始是一个空图,然后从小到大加边进去,如果加进去会形成环,就把环中最小的删掉。这样的话,复杂度就是O(n*m) ,这样就能AC了

代码:
#include<iostream>#include<cstdio>#include<algorithm>#include<string.h>#include<cstring>#include<vector>using namespace std;const int maxn = 355;const int inf = 1e8;int n , m , size , minw , ans;int fa[maxn];bool vis[maxn];int w[maxn][maxn];//int find(int x) { return x==fa[x] ? x : find(fa[x]); }struct Edge{int u , v , w;Edge(int uu,int vv,int ww) : u(uu) , v(vv) , w(ww) { }Edge() { }bool operator<(const Edge& e) const { return w < e.w; }}edge[maxn*maxn/2];int CA(int u,int v){memset(vis,0,sizeof(vis));int x = u;while (!vis[x]) {vis[x] = true;if (x==fa[x]) break;x = fa[x];}x = v;while (!vis[x] && fa[x]!=x) x = fa[x];if (vis[x]) return x;else return -1;}void findremove(const Edge&e){int rt = CA(e.u,e.v);if (rt==-1) return;Edge minedge;minedge.w = inf;int y = e.u ;int x = fa[y];while (x!=y && y!= rt) {if (w[x][y] < minedge.w) minedge = Edge(x,y,w[x][y]);y = x;x = fa[x];}y = e.v;x = fa[y];while (y!=rt && x!=y) {if (w[x][y] < minedge.w)minedge = Edge(x,y,w[x][y]);y = x;x = fa[x];}fa[minedge.v] = minedge.v;minw = inf;for (int i = 0 ; i < n ; ++i)if (fa[i]!=i && minw > w[fa[i]][i])minw = w[fa[i]][i];--size;}void addedge(const Edge & e){if (fa[e.u]==e.u) fa[e.u] = e.v; else if (fa[e.v]==e.v) fa[e.v] = e.u;else {vector<int> v;int x = e.u;while (true){v.push_back(x);if (x==fa[x]) break;x = fa[x];}for (int i = v.size()-1 ; i > 0 ; --i)fa[v[i]] = v[i-1];fa[e.u] = e.v;}minw = min(minw,e.w);++size;}void input(){scanf("%d",&m);int u , v , w;for (int i = 0 ; i < m ; ++i){scanf("%d%d%d",&u,&v,&w);edge[i] = Edge(u,v,w);::w[u][v] = ::w[v][u] = w;}}void solve(){size = 0;sort(edge,edge+m);for (int i = 0 ; i < n ; ++i) fa[i] = i;ans = minw = inf;for (int i = 0 ; i < m ; ++i){findremove(edge[i]);addedge(edge[i]);if (size==n-1) ans = min(ans,edge[i].w-minw);}printf("%d\n",ans);}int main(){//freopen("input.in","r",stdin);while (scanf("%d",&n)==1,n){input();solve();}return 0;}
0 0