usaco2007

版权声明:https://blog.csdn.net/huashuimu2003 https://blog.csdn.net/huashuimu2003/article/details/85196000

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;
}

猜你喜欢

转载自blog.csdn.net/huashuimu2003/article/details/85196000