CF 337D 求圆交

题目链接:http://codeforces.com/problemset/problem/337/D

题意:就是一棵树上,有一些点被来自东方的神秘力量影响的,力量影响范围是d,为可能的力量源有几个。

思路:相当于是找到距离这m的点的距离都不小于d的点的个数。

先从任意一个点一次dfs,找到m个点中距离最远的点,标记为max1,在以max1开始,dfs一遍,从数组d1记录各个点的距离,找到距离最远的点max2,再从max2开始跑一遍dfs,用d2记录距离。遍历所有点,到max1和max2的距离都小于d的点就成立。

//以上是题解讲的,但是我不懂为什么要先从任意一个点一次dfs,找到m个点中距离最远的点,再从这个点开始DFS。

//我写了一个直接找两个最远的点,求圆交的WA了。等我搞懂了再来补充。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
#define ll long long
const int maxn=1e5+5;
const int INF=0x3f3f3f3f;

int n,m,d;
int a[maxn],d1[maxn],d2[maxn];
int vit[maxn];
int head[maxn],k;

struct Edge
{
    int v;
    int next;
} edge[maxn<<1];

void init()
{
    k=0;
    memset(head,-1,sizeof(head));
    memset(d1,0,sizeof(d1));
    memset(d2,0,sizeof(d2));
}

void addedge(int u,int v)
{
    edge[k].v=v;
    edge[k].next=head[u];
    head[u]=k++;

    edge[k].v=u;
    edge[k].next=head[v];
    head[v]=k++;
}

void dfs1(int u,int t)
{
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        int v=edge[i].v;
        if(vit[v]==0)
        {
            vit[v]=1;
            d1[v]=t+1;
            dfs1(v,t+1);
        }
    }
}

void dfs2(int u,int t)
{
    for(int i=head[u]; i!=-1; i=edge[i].next)
    {
        int v=edge[i].v;
        if(vit[v]==0)
        {
            vit[v]=1;
            d2[v]=t+1;
            dfs2(v,t+1);
        }
    }
}

int main()
{
    //freopen("in.txt","r",stdin);
    while(scanf("%d%d%d",&n,&m,&d)==3)
    {
        init();
        for(int i=1; i<=m; i++) scanf("%d",&a[i]);
        int x,y;
        for(int i=1; i<n; i++)
        {
            scanf("%d%d",&x,&y);
            addedge(x,y);
        }

        memset(vit,0,sizeof(vit));
        vit[1]=1;
        dfs2(1,0);

        int dd=-INF,max1,max2;
        for(int i=1; i<=m; i++)
            if(d2[a[i]]>dd) dd=d2[a[i]],max1=a[i];

        memset(vit,0,sizeof(vit));
        vit[max1]=1;
        dfs1(max1,0);

        dd=-INF;
        for(int i=1; i<=m; i++)
            if(d1[a[i]]>dd) dd=d1[a[i]],max2=a[i];

        memset(d2,0,sizeof(d2));
        memset(vit,0,sizeof(vit));
        vit[max2]=1;
        dfs2(max2,0);

        int ans=0;
        for(int i=1; i<=n; i++)
            if(d1[i]<=d && d2[i]<=d)
                ans++;
        printf("%d\n",ans);
    }
    return 0;
}
时间: 2024-11-03 22:26:19

CF 337D 求圆交的相关文章

HDU5120 Intersection(求 圆交)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5120 题目大意: 给定两个圆环 求相交部分的面积 分析: 画一个图,然后看一看分析下就可以得到结论  ans=  两个大圆相交的部分 +两个小圆相交的部分 - 一大一小圆相交的部分 代码如下: #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using name

HDU3264 Open-air shopping malls (圆交+二分)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3264 题意: 给定n个圆的圆心和半径,求一个圆心为这些圆中任意一个,与所有圆相交的面积超过其面积一半的圆的最小半径. 分析: 枚举圆心,然后二分得到最小的半径,直接套求圆交的模板. 代码如下: #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using name

hdu4063(圆与圆交+线段与圆交+最短路)

写几何题总是提心吊胆.精度问题真心吓人. 其实思路挺简单的一道题,真是什么算法和几何double搞到一块,心里就虚虚的. 思路:求出所有圆之间的交点,然后用这些交点跑一遍最短路就可以了. Aircraft Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 1244    Accepted Submission(s): 304 Proble

Intersection(HDU5120 + 圆交面积)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5120 题目: 题意: 求两个圆环相交的面积. 思路: 两个大圆面积交-2×大圆与小圆面积交+两小圆面积交. 代码实现如下: 1 #include <set> 2 #include <map> 3 #include <deque> 4 #include <ctime> 5 #include <stack> 6 #include <cmath&g

JAVA求圆的面积

import java.text.DecimalFormat;import java.util.Scanner; public class TheAreaOfCircle { public static void main(String[] args) { /*问题描述 给定圆的半径r,求圆的面积. 输入格式 输入包含一个整数r,表示圆的半径. 输出格式 输出一行,包含一个实数,四舍五入保留小数点后7位,表示圆的面积. 说明:在本题中,输入是一个整数,但是输出是一个实数. 对于实数输出的问题,请

c++入门第一天(求圆的面积)

看了一会书,发现C++和C虽然于发上相似,但是解决问题的方式还是不一样的,毕竟面向对象和面向过程是两种不同的思维方式.下面就通过一个求圆的面积的例子,比较C和C++的不同. 需求:输入圆的半径,求解圆的面积 使用C语言来解决:1.定义两个变量半径r.面积s;  2.输入半径;  3.打印结果. 以下是源代码: #include <stdio.h> int main01() { double r, s; //定义变量圆和半径 printf("请输入圆的半径:"); scanf

编程题:带参数的宏定义来实现,求圆的周长和面积。

#include<stdio.h> #define PI 3.14159 #define L(r) 2*PI*(r) #define S(r) PI*(r)*(r) void main() { float radius,circle,area; scanf("%f",&radius); circle=L(radius); area=S(radius); printf("radius:%f\tcircle:%f\tarea:%f\n", radiu

OJ刷题之《默认参数--求圆的面积》

题目描述 根据半径r求圆的面积,如果不指定小数位数,输出结果默认保留两位小数. 部分代码已给定如下,只需要提交缺失的代码. #include <iostream> #include <iomanip> using namespace std; const double PI=3.14159; /* 补充缺少代码 */ int main() { double r; int precision; cin>>r>>precision; showarea(r); s

(c语法百题5)求圆的周长 和 面积

知识点: 头文件#define的用法 浮点型%f的用法,控制小数. 内容: 求圆的周长 和 面积 输入说明: 一行 ,半径值 ,实型 输出说明: pi=3.1415 情况 下 的 周长 和 面积 (保留2位小数),分两行输出 输入样例: 若题目没有特别说明,则应该以多组测试数据方式读取,或者参考a001. 10.0 输出样例 : 62.83 314.15 #include <stdio.h> #define pi 3.1415 int main() { float a; scanf("