Scx117
只一眼,便辽阔了时间。

题意:给你一棵边权都为1的树,要求选择互不相交的若干条路径,这些路径包含有所有点。

在每一条路径上选择一条边,放置一个动点,设置一个方向,它开始在该路径上来回运动,速度为1。每个点上都有一个停表,当有一个动点经过这个点时它清零。设res_i表示i停表的历史最大显示时间。设得res_1,res_2,res_3,……序列的字典序最小。

n<=100。(数据范围有时候是唬人的)

 

标程:

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=105;
 4 int n,u[N],v[N],head[N],rd[N],cnt,To[N];
 5 double ans[N];
 6 struct node{int to,next;}num[N*2];
 7 void add(int x,int y)
 8 {num[++cnt].to=y;num[cnt].next=head[x];head[x]=cnt;}
 9 void dfs(int x,int fa,double lst)
10 {
11     double e=2.0/rd[x];//注意用2.0/而不是2/! 
12     for (int i=head[x];i;i=num[i].next)
13       if (num[i].to!=fa)
14       {
15             lst+=e;while (lst>2) lst-=2;
16           int id=(i+1)/2;
17             if (lst<=1) To[id]=x,ans[id]=lst;
18              else To[id]=num[i].to,ans[id]=lst-1;
19          dfs(num[i].to,x,lst+1);
20       }
21 }
22 int main()
23 {
24     scanf("%d",&n);
25     for (int i=1;i<n;i++) scanf("%d%d",&u[i],&v[i]),add(u[i],v[i]),add(v[i],u[i]),rd[u[i]]++,rd[v[i]]++;
26     dfs(1,-1,0);
27     printf("%d\n",n-1);
28     for (int i=1;i<n;i++) printf("1 %d %d %d %.8lf\n",i,u[i]+v[i]-To[i],To[i],ans[i]);
29     return 0;
30 }

 

易错点:1.注意double的除法。

2.注意lst表示到动点到儿子的距离。往下一层dfs的时候注意变更。

 

题解:贪心+构造

发现当每一条边都独立为一条路径时,经过路径上每一个点的时间间隔是最小的。

因此发现某动点一来一回时间间隔为2,对于i点的停表,历史最大时间为2/deg[i]。一定可以构造出来。

dfs按照树的结构构造一下即可。

posted on 2018-05-21 15:38  Scx117  阅读(148)  评论(0编辑  收藏  举报