您的位置:首页 > 其它

[SGU280 Trade centers]

2012-03-24 22:41 211 查看
[关键字]:贪心

[题目大意]:在一个有n个点的树中选若干个点建设交易中心,要求每个点到交易中心所经过的道路数不能超过k,求最少需要建几个交易中心分别在什么地方。

//=========================================================================================

[分析]:如果两个服务站之间的距离不大于2*k+1,那么这两个服务站之间的点都是可以被服务到的。 这个时候我们先给叶子节点进行编号(编号表示一个点到其中特殊服务站的距离):设其编号为k+1。这样,保证了它下面的节点不会照顾到它,然后从叶子节点往上面操作。每次考虑节点非叶子节点i,设p是它的孩子节点中,编号最小的,q是孩子节点中编号最大的,那么,如果p+q+2<=2*k+1,则该节点可以被自己子树上的服务站照顾到,所以它到最近的站距离是p+1。因为很显然p<q,所以这个p+1<k,所以这个站就没有必要放置服务站了。若p+q+2>2*k+1,那么设它的标号为q+1,这时按到他相对远的节点算,从相对远的到他的路程为q+1。 如果它的标号为2k+1,就代表没有节点能访问到他,并且他到他子树上的服务站离他距离已经足够远了,所以我们要放置服务站,并且设置编号为0。最后还需要对根特殊处理一下。

[代码]:

View Code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>
#include<stack>
using namespace std;

const int MAXN=40000;

int n,m;
int d[MAXN],f[MAXN],dis[MAXN],ans[MAXN];
stack<int> s;
vector<int> e[MAXN];
vector<int>::iterator first[MAXN];

void DFS()
{
vector<int>::iterator i;
s.push(1);
f[1]=1;
while (!s.empty())
{
int u=s.top();
for (i=first[u];i<e[u].end();++i)
if (f[*i]==0)
{
f[*i]=u;
++d[u];
first[u]=i+1;
s.push(*i);
break;
}
if (i==e[u].end()) s.pop();
}
}

/*void DFS(int u)
{
vector<int>::iterator i;
for (i=e[u].begin();i<e[u].end();++i)
if (f[*i]==0)
{
f[*i]=u;
++d[u];
DFS(*i);
}
}*/

void Init()
{
scanf("%d%d",&n,&m);
for (int i=1;i<n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
for (int i=1;i<=n;++i) first[i]=e[i].begin();
//f[1]=1;
DFS();
//DFS(1);
//for (int i=1;i<=n;++i) printf("%d %d %d\n",i,f[i],d[i]);
}

void Solve()
{
memset(dis,0,sizeof(dis));
for (int i=1;i<=n;++i)
if (!d[i]) s.push(i),dis[i]=m+1;
int p,mindeep,maxdeep,sum=0;
while (!s.empty())
{
int u=s.top();
s.pop();
p=0,mindeep=n,maxdeep=0;
vector<int>::iterator i;
for (i=e[u].begin();i<e[u].end();++i)
if (f[*i]==u)
{
++p;
if (dis[*i]<mindeep) mindeep=dis[*i];
if (dis[*i]>maxdeep) maxdeep=dis[*i];
}
if (p)
if (p==1)
{
dis[u]=mindeep+1;
if (dis[u]==2*m+1) dis[u]=0;
}
else
{
if (mindeep+maxdeep+2<=2*m+1) dis[u]=mindeep+1; else dis[u]=maxdeep+1;
if (dis[u]==2*m+1) dis[u]=0;
}
if (dis[u]==0) ans[++sum]=u;
if (f[u]!=u)
if (--d[f[u]]==0) s.push(f[u]);
if (dis[1]>m) ans[++sum]=1;
}
printf("%d\n",sum);
for (int i=1;i<=sum;++i) printf("%d\n",ans[i]);
}

int main()
{
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
Init();
Solve();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: