p1936 [usaco2007dec_silver]修建道路
题目
https://www.luogu.org/problemnew/show/P2872
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1010;
inline int read()
{
int f=1,num=0;
char ch=getchar();
while (!isdigit(ch)) { if (ch=='-') f=-1; ch=getchar(); }
while (isdigit(ch)) num=(num<<1)+(num<<3)+(ch^48), ch=getchar();
return num*f;
}
int n,m,len=0;
int fa[maxn];
double ans;//输出实数型
struct road1
{
int x,y,id;
}a[maxn];//点的结构体
struct road2
{
road1 spot,ver;
double v;
}edge[maxn*maxn];//边的结构体
bool mycpy(road2 a,road2 b)
{
return a.v<b.v;
}//排序条件
int find(int x)//并查集
{
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void build()//建边,构图
{
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
if (i!=j)
{
edge[++len].spot=a[i],edge[len].ver=a[j];
edge[len].v=sqrt((double)(a[i].x-a[j].x)*(double)(a[i].x-a[j].x)
+(double)(a[i].y-a[j].y)*(double)(a[i].y-a[j].y));
//注意勾股定理,强制转化$double$类型
}
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;++i)
a[i].x=read(),a[i].y=read(),a[i].id=i;
//输入
for(int i=1;i<=n;++i)
fa[i]=i;//一开始的老大是自己
for(int i=1;i<=m;++i)
{
int x=read(),y=read();
int tx=find(x);
int ty=find(y);
fa[tx]=ty;
}
//连通已有的边
build();//建边,构图
//建一棵最小生成树
sort(edge+1,edge+len+1,mycpy);//排序,从小到大排,取最小边
for(int i=1;i<=len;++i)
{
int x=find(edge[i].spot.id);
int y=find(edge[i].ver.id);
//找各自的老大
if(x==y) continue;
ans+=edge[i].v,fa[x]=y;
//连通,并加上边的值
}
printf("%.2lf",ans);//输出,保留2位小数
return 0;
}
p1938 [usaco2007dec_gold]奶牛的旅行
题目
描述 Description
作为对奶牛们辛勤工作的回报,Farmer John决定带她们去附近的大城市玩
一天。旅行的前夜,奶牛们在兴奋地讨论如何最好地享受这难得的闲暇。
很幸运地,奶牛们找到了一张详细的城市地图,上面标注了城市中所有L(2
<= L <= 1000)座标志性建筑物(建筑物按1…L顺次编号),以及连接这些建筑
物的P(2 <= P <= 5000)条道路。按照计划,那天早上Farmer John会开车将奶牛
们送到某个她们指定的建筑物旁边,等奶牛们完成她们的整个旅行并回到出发点
后,将她们接回农场。由于大城市中总是寸土寸金,所有的道路都很窄,政府不
得不把它们都设定为通行方向固定的单行道。
尽管参观那些标志性建筑物的确很有意思,但如果你认为奶牛们同样享受穿
行于大城市的车流中的话,你就大错特错了。与参观景点相反,奶牛们把走路定
义为无趣且令她们厌烦的活动。对于编号为i的标志性建筑物,奶牛们清楚地知
道参观它能给自己带来的乐趣值F_i (1 <= F_i <= 1000)。相对于奶牛们在走路
上花的时间,她们参观建筑物的耗时可以忽略不计。
奶牛们同样仔细地研究过城市中的道路。她们知道第i条道路两端的建筑物
L1_i和L2_i(道路方向为L1_i -> L2_i),以及她们从道路的一头走到另一头所
需要的时间T_i(1 <= T_i <= 1000)。
为了最好地享受她们的休息日,奶牛们希望她们在一整天中平均每单位时间
内获得的乐趣值最大。当然咯,奶牛们不会愿意把同一个建筑物参观两遍,也就
是说,虽然她们可以两次经过同一个建筑物,但她们的乐趣值只会增加一次。顺
便说一句,为了让奶牛们得到一些锻炼,Farmer John要求奶牛们参观至少2个建
筑物。
请你写个程序,帮奶牛们计算一下她们能得到的最大平均乐趣值。
输入格式 Input Format
第1行: 2个用空格隔开的整数:L 和 P
第2…L+1行: 第i+1行仅有1个整数:F_i
第L+2…L+P+1行: 第L+i+1行用3个用空格隔开的整数:L1_i,L2_i以及T_i, 描述了第i条道路。
输出格式 Output Format
输出1个实数,保留到小数点后2位(直接输出,不要做任何特殊的取整操作),表示如果奶牛按题目中描述的一系列规则来安排她们的旅行的话,她们能获得的最大平均乐趣值
样例输入 Sample Input
5 7
30
10
10
5
10
1 2 3
2 3 2
3 4 5
3 5 2
4 5 5
5 1 3
5 2 2
样例输出 Sample Output
6.00
输出说明:
如果奶牛选择1 -> 2 -> 3 -> 5 -> 1的旅行路线,她们能得到的总乐趣值
为60,为此她们得花费10单位的时间在走路上。于是她们在这次旅行中的平均乐
趣值为6。如果她们走2 -> 3 -> 5 -> 2的路线,就只能得到30/6 = 5的平均乐
趣值。并且,任何去参观建筑物4的旅行路线的平均乐趣值都没有超过4。
时间限制 Time Limitation
1s
注释 Hint
来源 Source
usaco 2007 dec gold sightsee
代码
#include<bits/stdc++.h>
#define _ 100010
using namespace std;
const double eps=1e-8;
struct rec
{
int x,y,z;
}e[_];
inline int read()
{
int f=1,num=0;
char ch=getchar();
while (ch<'0'||ch>'9') { if (ch=='-') f=-1; ch=getchar(); }
while (ch>='0'&&ch<='9') num=(num<<1)+(num<<3)+ch-'0',ch=getchar();
return num*f;
}
int n,m,happy[_];
int ver[_],Next[_],head[_],len;
double edge[_],l,r;
void add(int x,int y,double z)
{
ver[++len]=y,edge[len]=z,Next[len]=head[x],head[x]=len;
}
double dist[_];
bool v[_];
int cnt[_];
queue<int>q;
inline bool spfa()
{
for (int i=1;i<=n;++i) dist[i]=-1e9;
memset(cnt,0,sizeof(cnt));
memset(v,0,sizeof(v));
dist[1]=0;
q.push(1);
while (!q.empty())
{
int x=q.front();
q.pop();
v[x]=0;
for (int i=head[x];i;i=Next[i])
{
int y=ver[i];
double z=edge[i];
if (dist[y]+eps<dist[x]+z)
{
dist[y]=dist[x]+z;
if (!v[y])
{
q.push(y),v[y]=1;
if (++cnt[y]>n) return true;
}
}
}
}
return false;
}
inline bool check(double v)
{
memset(head+1,0,sizeof(int)*n);
len=0;
for (int i=1;i<=m;++i)
add(e[i].x,e[i].y,happy[e[i].x]-e[i].z*v);
if (spfa()) return true;
else return false;
}
int main()
{
n=read(),m=read();
for (int i=1;i<=n;++i)
happy[i]=read();
for (int i=1;i<=m;++i)
{
int x=read(),y=read(),z=read();
e[i]=(rec){x,y,z};
r+=z;
}
while (l+eps<r)
{
double mid=(l+r)/2.0;
if (check(mid)) l=mid;
else r=mid;
}
printf("%.2f",l);
return 0;
}