1845: Sensor network
链接 1845: Sensor network
题意: 给出一些传感器以及他们连接起来的网络,每个传感器都有其额 定电压,要求通过的电压只能高不能低。现在只能在一个传感器 上施加电压,然后问如果要使得网络中的每个点都能够有电,这 样的一个网络中各个传感器之间的极差最小是多少。
分析:很显然的,要使得网络中的每一个点都连通电,必须要连上n-1条边。然后 求连的所有边的边权的极差最小,我们没有必要把多余的边添加进来,即直 接判断生成树的极差即可。问题变为了找一棵边权极差最小的生成树。 根据贪心的思想,我们首先要像kruskal那样对所有边按照边权值来排序,排 序之后,连续的几条边如果构成生成树,那么这棵生成树的极差就是备选解。 即不用考虑非连续的情况,因为非连续情况一定有比他更优的解。这样,我 们只需要枚举这个连续的区间了。我们设定一个集合f,边按照从小到大的顺 序依次次检索,如果该边连接的两点不连通,即不构成环,那么我们连这条 边,并把边加入集合f。如果两点已经连通,那么,删除两点路径上边权最小 的边,然后再连上这条边。当集合的大小为n-1时,说明已经构成了一棵生 成树,那么我们把备选解与最终解进行比较即可。
代码:
#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;
int n,m;
struct Edge{
int u,v;
int val;
};
bool cmp(Edge a,Edge b){
return a.val<b.val;
}
Edge edge[355*355/2];
vector<int>q,G[500];
int fa[500];
int mp[500][500];//mp[i][j]来保存i-->j的权值
int num[500][500];//用num[i][j]来标记i-->j是第几条边
void dfs(int u){//通过dfs来求父节点
for (int i=0;i<G[u].size();i++){
if (fa[G[u][i]]==0){
fa[G[u][i]]=u;//父节点为u
dfs(G[u][i]);
}
}
}
int LCA(int u,int v){
for (int i=0;i<=n;i++){
fa[i]=0;
G[i].clear();
}
//从已经选择的边来构图找最小的边
for (int i=0;i<q.size();i++){
int x=edge[q[i]].u;
int y=edge[q[i]].v;
G[x].push_back(y);
G[y].push_back(x);
}
fa[v]=-1;
dfs(v);
if (!fa[u]) return -1;//相当于u,v不在一个连通块中,直接返回-1
int ans=1e9;
int place=-1;
while (u!=v){//找u-->v路径上的权值最小的边
if (ans>mp[u][fa[u]]){
ans=mp[u][fa[u]];
place=num[u][fa[u]];
}
u=fa[u];
}
return place;//将最短的边返回去
}
int main()
{
while (scanf ("%d",&n)){
if (n==0)break;
scanf ("%d",&m);
for (int i=0;i<m;i++){
scanf ("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].val);
edge[i].u++;edge[i].v++;
mp[edge[i].u][edge[i].v]=edge[i].val;//保存权值
mp[edge[i].v][edge[i].u]=edge[i].val;
}
sort(edge,edge+m,cmp);
q.clear();
int ans=1e9;
for (int i=0;i<m;i++){
num[edge[i].u][edge[i].v]=i;//保存边的编号
num[edge[i].v][edge[i].u]=i;
int place=LCA(edge[i].u,edge[i].v);
if (place>=0){//产生连通,则去掉最小的权值的一条边
vector<int>::iterator iter;
iter=lower_bound(q.begin(),q.end(),place);//二分找到place的位置
q.erase(iter);
}
q.push_back(i);
if (q.size()==n-1){
ans=min(ans,edge[i].val-edge[q[0]].val);
}
}
printf ("%d\n",ans);
}
return 0;
}