[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
[题目大意]:在一个有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; }
相关文章推荐
- 1 World Trade Center is open for business
- iOS之 view视图的创建和它的Frame、bounds、center属性
- transform和frame bounds center的混合开发
- 280. Wiggle Sort
- Apple Notification Center Service--ANCS【转】
- SGU 261 Discrete Roots(原根+高次同余方程+线性同余方程)
- iOS中NSNotificationCenter的简单使用
- 关于NSNotificationCenter的注册和移除
- SGU 531 Bonnie and Clyde(二分)
- How to Use the Visual Studio .NET Application Center Test
- hdu1009 FatMouse' Trade(贪心水)
- China: Second Largest Monthly Trade Surplus Recorded
- 1009 FatMouse' Trade 贪心
- [导入]微软推出Live Developer Center!
- 动态规划(方案还原):SGU 104 Little shop of flowers
- CSS中div、span和center元素
- leetcode 280: Wiggle Sort
- 微软推出新手程序员学习中心—Beginner Developer Learning Center
- <td width="172" rowspan="2" align="center"><?php echo "<img src=\"$icon\">";?></td>
- Unix-center.net用户空间提升到100M