您的位置:首页 > 其它

【NOIP2016提高A组集训第12场11.10】图的半径

2016-11-10 21:42 351 查看

Description



mhy12345学习了树的直径,于是开始研究图的半径,具体来说,我们需要在图中选定一个地方作为中心,其中这个中心有可能在路径上。

而这个中心的选址需要能够使得所有节点达到这个中心的最短路里面最大值最小(也就是说离中心最远的结点距离尽可能小),求出这个最大值的最小值,作为图的半径。

Solution

看到这题,一开始不是怎么会做,但是看到n≤200,就想开始打暴力。

暴力打着打着发现,好像很可做喔!!!!!

然后枚举每一条边,它有起点x和终点y,因为要找最长的路,那么把n个点到x和y的距离都求出来放进一个数组里面按到x为第一关键字(从大到小),到y为第二关键字(从小到大)因为要尽量的保证最大值尽量的小(把大的尽量踢掉)。然后排序之后把第i个点和i+1个点进行配对,设a为i到y从1到i的最大值,b为i+1到x的值(为什么要这样选?因为i到x同样的情况下选y会比后面的要优,对于选x,后面的会比前面的要优),那么其中的最小值+边权如果小于等于最大值,那么说明最大值很大,这个边权不能影响;否则这个边权可以影响最大值,那么答案就是两个值加起来在加上边权除以2。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=20000;
int i,j,k,l,n,m,z,da,x,y;
int f[207][207];
int a[maxn],b[maxn],c[maxn],yi,er,o,cnt;
int ans,yuan[207];
double ans1;
struct node{
int a,b;
}q[maxn];
bool cmp(node x,node y){
return x.a>y.a||x.a==y.a&&x.b<y.b;
}
int main(){
freopen("radius.in","r",stdin);
freopen("radius.out","w",stdout);
//  freopen("data.in","r",stdin);
scanf("%d%d",&n,&m);
memset(f,127/2,sizeof(f));da=f[0][0];
fo(i,1,m){
scanf("%d%d%d",&k,&l,&z);
f[k][l]=f[l][k]=min(f[k][l],z);
a[i]=k,b[i]=l,c[i]=z;
}
fo(i,1,n)f[i][i]=0;
fo(k,1,n){
fo(i,1,n){
fo(j,1,n){
if(f[i][k]+f[k][j]<f[i][j])f[i][j]=f[i][k]+f[k][j];
}
}
}
ans=0x7fffffff;
fo(i,1,n){
k=0;
fo(j,1,n)k=max(k,f[i][j]);
ans=min(k*2,ans);
}
fo(j,1,m){
x=a[j],y=b[j];
fo(i,1,n)q[i].a=f[x][i],q[i].b=f[y][i];
// p=t.top();
sort(q+1,q+1+n,cmp);
yi=o=0;
fo(i,1,n-1){
if(q[i].b>o)yi=q[i].b;else yi=o;
er=q[i+1].a;
o=yi;
if(yi>er){k=yi;yi=er;er=k;}
if(yi+c[j]<=er){
if(er*2<ans)ans=er*2;
}
else if(yi+er+c[j]<ans)ans=yi+er+c[j];
}
}
ans1=ans*1.0/2;
printf("%.2lf\n",ans1);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: