【noip2007】树网的核
来源:互联网 发布:深圳水务集团网络投诉 编辑:程序博客网 时间:2024/05/14 07:33
题目描述
设T=(V, E, W) 是一个无圈且连通的无向图(也称为无根树),每条边到有正整数的权,我们称T为树网(treebetwork),其中V,E分别表示结点与边的集合,W表示各边长度的集合,并设T有n个结点。
路径:树网中任何两结点a,b都存在唯一的一条简单路径,用d(a, b)表示以a, b为端点的路径的长度,它是该路径上各边长度之和。我们称d(a, b)为a, b两结点间的距离。
D(v, P)=min{d(v, u), u为路径P上的结点}。
树网的直径:树网中最长的路径成为树网的直径。对于给定的树网T,直径不一定是唯一的,但可以证明:各直径的中点(不一定恰好是某个结点,可能在某条边的内部)是唯一的,我们称该点为树网的中心。
偏心距ECC(F):树网T中距路径F最远的结点到路径F的距离,即
ECC(F)=max{d(v, F),v∈V}
任务:对于给定的树网T=(V, E, W)和非负整数s,求一个路径F,他是某直径上的一段路径(该路径两端均为树网中的结点),其长度不超过s(可以等于s),使偏心距ECC(F)最小。我们称这个路径为树网T=(V, E, W)的核(Core)。必要时,F可以退化为某个结点。一般来说,在上述定义下,核不一定只有一个,但最小偏心距是唯一的。
下面的图给出了树网的一个实例。图中,A-B与A-C是两条直径,长度均为20。点W是树网的中心,EF边的长度为5。如果指定s=11,则树网的核为路径DEFG(也可以取为路径DEF),偏心距为8。如果指定s=0(或s=1、s=2),则树网的核为结点F,偏心距为12。
输入输出格式
输入格式:
输入文件core.in包含n行:
第1行,两个正整数n和s,中间用一个空格隔开。其中n为树网结点的个数,s为树网的核的长度的上界。设结点编号以此为1,2,……,n。
从第2行到第n行,每行给出3个用空格隔开的正整数,依次表示每一条边的两个端点编号和长度。例如,“2 4 7”表示连接结点2与4的边的长度为7。
输出格式:
输出文件core.out只有一个非负整数,为指定意义下的最小偏心距。
输入输出样例
输入样例#1: 复制
5 2
1 2 5
2 3 2
2 4 4
2 5 3
输出样例#1: 复制
5
输入样例#2: 复制
8 6
1 3 2
2 3 2
3 4 6
4 5 3
4 6 4
4 7 2
7 8 3
输出样例#2: 复制
5
说明
40%的数据满足:5<=n<=15
70%的数据满足:5<=n<=80
100%的数据满足:5<=n<=300,0<=s<=1000。边长度为不超过1000的正整数
NOIP 2007 提高第四题
终于能够独立AC T4 了,3.5h惊天大模拟;
本蒟蒻看不出算法,只好模拟+暴力+最短路;
没想到竟然过了
简要说下思路:
一:跑个Floyed求出两点之间的距离(好像有点浪费,但数据范围这么小,就瞎写吧。。)
二:跑bfs求出图中最长的路径(即题中的直径),实现方法上:建一个结构体Node 存储点的 id(编号),dis(距离起点的距离),step(到达这个点时走的步数),pre(这个点的前驱),然后一起扔到队列里。与当前最优值更新存到road里即可;
在这里我是选取出度为1的点广搜的,小贪心,很容易理解吧
三:接下来就是暴力的不能再暴力了
枚举直径上所有的合法的路径,对于每一条路径枚举所有的点到这条路径的最小值,在这些里面选一个最大值(最远距离)。最后取所有的路径中的最小值(最小的最大偏心距)。输出即可。
Code:
#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;int n,s,chu[301];struct Edge{ int to,next,dis;}edge[1001];bool b[301];struct Node{ int id,dis,step,pre;}node[301];queue<Node> que;int maxstep; int nowmax=0;//nowmax不能放在spfa里面啊 int f[301][301];int ans=0x7fffffff;int head[301],num_edge;void add_edge(int from,int to,int dis){ edge[++num_edge].next=head[from]; edge[num_edge].to=to; edge[num_edge].dis=dis; head[from]=num_edge;}int maxdis; int road[301],tot;void dfs(int x,int step,int dis)//这是用深搜写的求直径的方法,但是不知道为什么WA了几个点,大佬们帮我看看也好 { if (step==1) road[1]=x; if (dis>maxdis) { maxdis=dis; road[step]=x; maxstep=step; } b[x]=true; for (int i=head[x]; i!=0; i=edge[i].next) { if (!b[edge[i].to]) { dfs(edge[i].to,step+1,dis+edge[i].dis); } }}void spfa(int x){ memset(b,0,sizeof(b));//不要忘记每次清零 memset(node,0,sizeof(node)); b[x]=true;//起点标记 for (int i=1; i<=n; i++) node[i].id=i; node[x].dis=0; node[x].step=1; que.push(node[x]); while (!que.empty()) { Node now=que.front(); que.pop(); int t=0; for (int i=head[now.id]; i!=0; i=edge[i].next) { if (!b[edge[i].to]) { t++; b[edge[i].to]=true; node[edge[i].to].dis=now.dis+edge[i].dis; node[edge[i].to].pre=now.id; node[edge[i].to].step=now.step+1; que.push(node[edge[i].to]); } }// if (nowmax<now.dis&&!t)//从终点(没有出度)向前保存路径 if (nowmax<now.dis&&chu[now.id]==1&&now.id!=x) { nowmax=now.dis; maxstep=now.step; road[now.step]=now.id; int p=now.pre; while (p) { road[node[p].step]=node[p].id; p=node[p].pre; } } }}void Floyed(){ for (int k=1; k<=n; k++) for(int i=1; i<=n; i++) for (int j=1; j<=n; j++)// if (i!=j&&j!=k&&i!=k) f[i][j]=min(f[i][j],f[i][k]+f[k][j]);/* for (int i=1; i<=n; i++) { for(int j=1; j<=n; j++) printf("%d ",f[i][j]); printf("\n"); }*/}bool vis[301],used[301]; int max_dis;void work(int x,int y){ int road_max=0; for (int i=1; i<=n; i++) { int node_min=0x7fffffff; for (int j=x; j<=y; j++) {// if (i!=road[j]) node_min=min(node_min,f[i][road[j]]); } road_max=max(road_max,node_min); } ans=min(ans,road_max);}int main(){ scanf("%d%d",&n,&s); memset(f,0x7f/3,sizeof(f)); for (int i=1; i<=n; i++) f[i][i]=0; for (int i=1; i<=n-1; i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add_edge(x,y,z); add_edge(y,x,z); f[x][y]=f[y][x]=z; chu[x]++; chu[y]++; } Floyed(); for (int i=1; i<=n; i++) if (chu[i]==1) {// dfs(i,1,0); spfa(i); }/* int maxn=0; int k; for (int i=head[road[2]]; i!=0; i=edge[i].next) if (maxn<edge[i].dis) {maxn=edge[i].dis; k=edge[i].to;} road[1]=k; for (int i=1; i<=maxstep; i++) printf("%d ",road[i]);*/ for (int i=1; i<=maxstep; i++) { for (int j=i; j<=maxstep; j++) { if (f[road[i]][road[j]]>s) break; work(i,j); } } printf("%d",ans); return 0;}
- NOIP2007 树网的核
- 【noip2007】树网的核
- 【noip2007】树网的核
- NOIP2007 树网的核
- noip2007 树网的核
- [noip2007]树网的核
- 【noip2007】树网的核
- 1999: [Noip2007]Core树网的核
- 1999: [Noip2007]Core树网的核
- BZOJ1999 && noip2007树网的核
- NOIP2007 树网的核 [dfs] [数据结构] [树的直径]
- NOIP2007第四题 树网的核 分析
- ACM 97. [NOIP2007] 树网的核(Floyd+枚举)
- [NOIP2007]树网的核【搜索,最短路…
- noip2007 树网的核 (floyd预处理+暴力枚举)
- BZOJ 1999: [Noip2007]Core树网的核[dfs]
- BZOJ 1999: [Noip2007]Core树网的核【最长链】
- [noip2007]树网的核(链上乱搞)
- SpringMVC与Struts2区别与比较总结
- maven包含Main类的项目打包
- sqlServer
- TCP协议栈知识实例
- 函数
- 【noip2007】树网的核
- DjVu格式的两大优势?
- Linux下切换Python版本
- Java设计模式(四) 观察者模式
- Spring+SpringMVC+MyBatis+easyUI整合基础篇(三)搭建步骤
- Android7 imx6 Selinux
- 关于const的使用
- 使用nginx+tomcat实现集群
- Effective Java