poj3107、2378、1655(树形DP,割点)

地址:3107:http://poj.org/problem?id=3107

            2378:http://poj.org/problem?id=2378

            1655:http://poj.org/problem?id=1655

这三道题比较相似,我就写在一起了。

3107:Godfather

Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 4636 Accepted: 1575

Description

Last years Chicago was full of gangster fights and strange murders. The chief of the police got really tired of all these crimes, and decided to arrest the mafia leaders.

Unfortunately, the structure of Chicago mafia is rather complicated. There are n persons known to be related to mafia. The police have traced their activity for some time, and know that some of them are communicating with each other. Based on the data collected, the chief of the police suggests that the mafia hierarchy can be represented as a tree. The head of the mafia, Godfather, is the root of the tree, and if some person is represented by a node in the tree, its direct subordinates are represented by the children of that node. For the purpose of conspiracy the gangsters only communicate with their direct subordinates and their direct master.

Unfortunately, though the police know gangsters’ communications, they do not know who is a master in any pair of communicating persons. Thus they only have an undirected tree of communications, and do not know who Godfather is.

Based on the idea that Godfather wants to have the most possible control over mafia, the chief of the police has made a suggestion that Godfather is such a person that after deleting it from the communications tree the size of the largest remaining connected component is as small as possible. Help the police to find all potential Godfathers and they will arrest them.

Input

The first line of the input file contains n — the number of persons suspected to belong to mafia (2 ≤ n ≤ 50 000). Let them be numbered from 1 to n.

The following n − 1 lines contain two integer numbers each. The pair aibi means that the gangster ai has communicated with the gangster bi. It is guaranteed that the gangsters’ communications form a tree.

Output

Print the numbers of all persons that are suspected to be Godfather. The numbers must be printed in the increasing order, separated by spaces.

Sample Input

6
1 2
2 3
2 5
3 4
3 6

Sample Output

2 3

题意:删除某个点,使得剩下分块中最大节点数最少,输出该点(若答案有多个点,按顺序输出)。

思路:两遍搜索。第一遍以其中一个点为根节点,将所有点的子节点个数求出。第二遍搜索根据记录的子节点情况求出删除该点后所剩部分中最大的一块含有的点数。

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define Ma 50010
struct node{
    int to,next;
}tree[Ma*2];
int n,kk=0,head[Ma*2],f[Ma],ans[Ma];
void add(int fa,int son){
    tree[kk].to=son;
    tree[kk].next=head[fa];
    head[fa]=kk++;
}
void dfs(int son,int fa){  //第一遍搜索
    int to;
    for(int i=head[son];i!=-1;i=tree[i].next){
        to=tree[i].to;
        if(to!=fa){
            dfs(to,son);
            f[son]+=f[to];
        }
    }
}
void dfsans(int son,int fa){  //第二遍搜索
    int to,a,b;
    for(int i=head[son];i!=-1;i=tree[i].next){
        to=tree[i].to;
        ans[son]=max(f[to],ans[son]);
        if(to!=fa){  //根据子节点个数求最大块的点数
            a=f[son];
            b=f[to];
            f[son]=a-b;
            f[to]=a;
            dfsans(to,son);
            f[son]=a;
            f[to]=b;
        }
    }
}
int main(){
    scanf("%d",&n);
    int fa,son;
    memset(head,-1,sizeof(head));
    for(int i=1;i<n;i++){
        scanf("%d%d",&fa,&son);
        add(fa,son);
        add(son,fa);
        f[i]=1;
    }
    f[n]=1;
    dfs(1,-1);
    dfsans(1,-1);
    int minn=Ma,ss=0;
    for(int i=1;i<=n;i++)
        minn=min(minn,ans[i]);
    for(int i=1;i<=n;i++)
        if(ans[i]==minn){
            if(ss) printf(" %d",i);
            else{
                printf("%d",i);
                ss=1;
            }
        }
    puts("");
    return 0;
}

1655:Balancing Act

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 8687 Accepted: 3584

Description

Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the largest tree in the forest T created by deleting that node from T. 
For example, consider the tree: 

Deleting node 4 yields two trees whose member nodes are {5} and {1,2,3,6,7}. The larger of these two trees has five nodes, thus the balance of node 4 is five. Deleting node 1 yields a forest of three trees of equal size: {2,6}, {3,7}, and {4,5}. Each of these trees has two nodes, so the balance of node 1 is two. 

For each input tree, calculate the node that has the minimum balance. If multiple nodes have equal balance, output the one with the lowest number. 

Input

The first line of input contains a single integer t (1 <= t <= 20), the number of test cases. The first line of each test case contains an integer N (1 <= N <= 20,000), the number of congruence. The next N-1 lines each contains two space-separated node numbers that are the endpoints of an edge in the tree. No edge will be listed twice, and all edges will be listed.

Output

For each test case, print a line containing two integers, the number of the node with minimum balance and the balance of that node.

Sample Input

1
7
2 6
1 2
1 4
4 5
3 7
3 1

Sample Output

1 2

题意:删除某个点,使得剩下最大节点数最少,输出该点以及删掉该点后的最大节点数(若有多个点,输出序号最小的那个)。

思路:同上,注意N的最大值以及赋初值。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define Ma 20010
struct node
{
    int to,next;
} tree[Ma*2];
int n,kk,head[Ma*2],f[Ma],ans[Ma];
void add(int fa,int son)
{
    tree[kk].to=son;
    tree[kk].next=head[fa];
    head[fa]=kk++;
}
void dfs(int son,int fa)
{
    int to;
    for(int i=head[son]; i!=-1; i=tree[i].next)
    {
        to=tree[i].to;
        if(to!=fa)
        {
            dfs(to,son);
            f[son]+=f[to];
        }
    }
}
void dfsans(int son,int fa)
{
    int to,a,b;
    for(int i=head[son]; i!=-1; i=tree[i].next)
    {
        to=tree[i].to;
        ans[son]=max(f[to],ans[son]);
        if(to!=fa)
        {
            a=f[son];
            b=f[to];
            f[son]=a-b;
            f[to]=a;
            dfsans(to,son);
            f[son]=a;
            f[to]=b;
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int fa,son;
        kk=0;  //注意赋初值
        memset(head,-1,sizeof(head));
        memset(ans,0,sizeof(ans));
        for(int i=1; i<n; i++)
        {
            scanf("%d%d",&fa,&son);
            add(fa,son);
            add(son,fa);
            f[i]=1;
        }
        f[n]=1;
        dfs(1,-1);
        dfsans(1,-1);
        int minn=Ma,ss=0;
        for(int i=1; i<=n; i++)
        {
            if(minn>ans[i])
            {
                minn=ans[i];
                ss=i;
            }
        }
        printf("%d %d\n",ss,minn);
    }
    return 0;
}

2378:Tree Cutting

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 3627 Accepted: 2152

Description

After Farmer John realized that Bessie had installed a "tree-shaped" network among his N (1 <= N <= 10,000) barns at an incredible cost, he sued Bessie to mitigate his losses. 

Bessie, feeling vindictive, decided to sabotage Farmer John's network by cutting power to one of the barns (thereby disrupting all the connections involving that barn). When Bessie does this, it breaks the network into smaller pieces, each of which retains full connectivity within itself. In order to be as disruptive as possible, Bessie wants to make sure that each of these pieces connects together no more than half the barns on FJ. 

Please help Bessie determine all of the barns that would be suitable to disconnect.

Input

* Line 1: A single integer, N. The barns are numbered 1..N. 

* Lines 2..N: Each line contains two integers X and Y and represents a connection between barns X and Y.

Output

* Lines 1..?: Each line contains a single integer, the number (from 1..N) of a barn whose removal splits the network into pieces each having at most half the original number of barns. Output the barns in increasing numerical order. If there are no suitable barns, the output should be a single line containing the word "NONE".

Sample Input

10
1 2
2 3
3 4
4 5
6 7
7 8
8 9
9 10
3 8

Sample Output

3
8

Hint

INPUT DETAILS: 

The set of connections in the input describes a "tree": it connects all the barns together and contains no cycles. 

OUTPUT DETAILS: 

If barn 3 or barn 8 is removed, then the remaining network will have one piece consisting of 5 barns and two pieces containing 2 barns. If any other barn is removed then at least one of the remaining pieces has size at least 6 (which is more than half of the original number of barns, 5).

题意:删除某个点,使剩下的最大节点数少于总结点数的一半,问有多少情况。

思路:同上,先求出所有点的删除后的最大节点数,在顺序输出该值小于总结点数一半的点的标号。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define Ma 10010
struct node{
    int to,next;
}tree[Ma*2];
int n,kk=0,head[Ma*2],f[Ma],ans[Ma];
void add(int fa,int son){
    tree[kk].to=son;
    tree[kk].next=head[fa];
    head[fa]=kk++;
}
void dfs(int son,int fa){
    int to;
    for(int i=head[son];i!=-1;i=tree[i].next){
        to=tree[i].to;
        if(to!=fa){
            dfs(to,son);
            f[son]+=f[to];
        }
    }
}
void dfsans(int son,int fa){
    int to,a,b;
    for(int i=head[son];i!=-1;i=tree[i].next){
        to=tree[i].to;
        ans[son]=max(f[to],ans[son]);
        if(to!=fa){
            a=f[son];
            b=f[to];
            f[son]=a-b;
            f[to]=a;
            dfsans(to,son);
            f[son]=a;
            f[to]=b;
        }
    }
}
int main(){
    scanf("%d",&n);
    int fa,son;
    memset(head,-1,sizeof(head));
    for(int i=1;i<n;i++){
        scanf("%d%d",&fa,&son);
        add(fa,son);
        add(son,fa);
        f[i]=1;
    }
    f[n]=1;
    dfs(1,-1);
    dfsans(1,-1);
    int minn=Ma,ss=0;
    for(int i=1;i<=n;i++)
        if(ans[i]<=n/2) printf("%d\n",i);
    puts("");
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
目标检测(Object Detection)是计算机视觉领域的一个核心问题,其主要任务是找出图像中所有感兴趣的目标(物体),并确定它们的类别和位置。以下是对目标检测的详细阐述: 一、基本概念 目标检测的任务是解决“在哪里?是什么?”的问题,即定位出图像中目标的位置并识别出目标的类别。由于各类物体具有不同的外观、形状和姿态,加上成像时光照、遮挡等因素的干扰,目标检测一直是计算机视觉领域最具挑战性的任务之一。 二、核心问题 目标检测涉及以下几个核心问题: 分类问题:判断图像中的目标属于哪个类别。 定位问题:确定目标在图像中的具体位置。 大小问题:目标可能具有不同的大小。 形状问题:目标可能具有不同的形状。 三、算法分类 基于深度学习的目标检测算法主要分为两大类: Two-stage算法:先进行区域生成(Region Proposal),生成有可能包含待检物体的预选框(Region Proposal),再通过卷积神经网络进行样本分类。常见的Two-stage算法包括R-CNN、Fast R-CNN、Faster R-CNN等。 One-stage算法:不用生成区域提议,直接在网络中提取特征来预测物体分类和位置。常见的One-stage算法包括YOLO系列(YOLOv1、YOLOv2、YOLOv3、YOLOv4、YOLOv5等)、SSD和RetinaNet等。 四、算法原理 以YOLO系列为例,YOLO将目标检测视为回归问题,将输入图像一次性划分为多个区域,直接在输出层预测边界框和类别概率。YOLO采用卷积网络来提取特征,使用全连接层来得到预测值。其网络结构通常包含多个卷积层和全连接层,通过卷积层提取图像特征,通过全连接层输出预测结果。 五、应用领域 目标检测技术已经广泛应用于各个领域,为人们的生活带来了极大的便利。以下是一些主要的应用领域: 安全监控:在商场、银行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值