P5157 [USACO18DEC]The Cow Gathering

题目链接

题意分析

题意

给你一棵树 每一次都会删除一个叶子节点 同时树上存在一些有向边\((a,b)\)

必须满足\(a\)\(b\)之前删除

问每一个节点作为根节点时是否存在合法的删边情况 使得跟、根节点被最后一个删除


换根\(dp\)\(No\)

首先有向边必定形成一个或者多个\(DAG\)

所以先判断是否有环

然后做做这道题 遥远的国度

以当前点作为根节点不合法的情况就是

存在有向边\((a,b)\)满足\(a\)\(b\)的祖先

那么我们对于每一条有向边分开讨论判断那些节点在当前有向边情况下可以成为根节点

同那道题 分情况讨论

1.\(a\)\(b\)的祖先

那么只有\(a\)的子树(不包括\(a\))可以成为根节点

2.\(a\)不是\(b\)的祖先

那么只有\(a\)的子树(包括\(a\))不可以成为根节点

然后我们使用\(dfs\)序实现区间覆盖就可以了

CODE:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<cstdlib>
#include<string>
#include<queue>
#include<map>
#include<stack>
#include<list>
#include<set>
#include<deque>
#include<vector>
#include<ctime>
#define ll long long
#define inf 0x7fffffff
#define N 500008
#define IL inline
#define M 508611
#define D double
#define ull unsigned long long
#define R register
using namespace std;
template<typename T>IL void read(T &_)
{
    T __=0,___=1;char ____=getchar();
    while(!isdigit(____)) {if(____=='-') ___=0;____=getchar();}
    while(isdigit(____)) {__=(__<<1)+(__<<3)+____-'0';____=getchar();}
    _=___ ? __:-__;
}
/*-------------OI使我快乐-------------*/
int n,m,tot,cnt,top,all;
int to[M],nex[M],head[M],ans[M];
int dep[M],fath[M][20],siz[M];
int dfn[M],wt[M],tre[M],in[M];
int dfnn[M],low[M],sta[M];
bool vis[M];
vector<int> G[M];
bool flag;
IL void add_edge(int x,int y)
{;to[++tot]=y;nex[tot]=head[x];head[x]=tot;}
IL void add(int x,int y)
{for(;x<=n;x+=x&-x) tre[x]+=y;}
IL int qury(int x)
{int res=0;for(;x;x-=x&-x) res+=tre[x];return res;}
IL void dfs(int now,int fat,int deep)
{
    dep[now]=deep;fath[now][0]=fat;dfn[now]=++cnt;wt[cnt]=now;siz[now]=1;
    for(R int i=1;i<=19;++i) fath[now][i]=fath[fath[now][i-1]][i-1];
    for(R int i=head[now];i;i=nex[i])
    {
        int v=to[i];
        if(v==fat) continue;
        dfs(v,now,deep+1);
        siz[now]+=siz[v];
    }
}
IL int LCA(int nowx,int nowy)
{
    if(dep[nowx]<dep[nowy]) swap(nowx,nowy);
    for(R int i=19;i>=0;--i)
    if(dep[fath[nowx][i]]>=dep[nowy]) nowx=fath[nowx][i];
    if(nowx==nowy) return nowx;
    for(R int i=19;i>=0;--i)
    if(fath[nowx][i]!=fath[nowy][i]) 
    nowx=fath[nowx][i],nowy=fath[nowy][i];
    return fath[nowx][0];
}
IL void update(int x,int y)
{
    if(x>y) return;
    add(x,1);add(y+1,-1);
}
IL void Tarjan(int now)
{
    dfnn[now]=low[now]=++cnt;
    vis[now]=1;sta[++top]=now;
    for(R int i=0;i<(int)G[now].size();++i)
    {
        int v=G[now][i];
        if(!dfnn[v]) Tarjan(v),low[now]=min(low[now],low[v]);
        else if(vis[v]) low[now]=min(low[now],dfnn[v]);
    }
    if(low[now]==dfnn[now])
    {
        all=0;
        while(sta[top+1]!=now)
        {
            ++all;
            vis[sta[top--]]=0;
        }
        if(all>1) flag=1;
    }
}
int main()
{
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(n);read(m);
//  puts("0");return 0;
    for(R int i=1,x,y;i<n;++i)
    {
        read(x);read(y);
        add_edge(x,y);add_edge(y,x);
    }
    dfs(1,0,1);
//  for(R int i=1;i<=n;++i) printf("%d%c",siz[i],(i==n ? '\n':' '));
    for(R int i=1,x,y;i<=m;++i)
    {
        read(x);read(y);
        G[x].push_back(y);
        int lca=LCA(x,y);
//      printf("lca=%d\n",lca);
        if(lca==x)
        {
//          puts("now cdy");
            int now=y;
            for(R int i=19;i>=0;--i)
            if(fath[now][i]&&dep[fath[now][i]]>dep[x]) now=fath[now][i];
//          printf("now at %d\n",now);
//          printf("(%d , %d)\n",dfn[now],dfn[now]+siz[now]-1);
            update(dfn[now],dfn[now]+siz[now]-1);
        }
        else
        {
//          puts("now wzy");
            update(1,dfn[x]-1);update(dfn[x]+siz[x],n);
        }
    }
    for(R int i=n;i;--i) if(!dfnn[i]) Tarjan(i);
    if(flag)
    for(R int i=1;i<=n;++i) puts("0");
//  for(R int i=1;i<=n;++i) printf("%d\n",qury(1))
    else 
    for(R int i=1;i<=n;++i) printf("%d\n",qury(dfn[i])==m);
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}

HEOI 2019 RP++

转载于:https://www.cnblogs.com/LovToLZX/p/10612520.html

先展示下效果 https://pan.quark.cn/s/a4b39357ea24 遗传算法 - 简书 遗传算法的理论是根据达尔文进化论而设计出来的算法: 人类是朝着好的方向(最优解)进化,进化过程中,会自动选择优良基因,淘汰劣等基因。 遗传算法(英语:genetic algorithm (GA) )是计算数学中用于解决最佳化的搜索算法,是进化算法的一种。 进化算法最初是借鉴了进化生物学中的一些现象而发展起来的,这些现象包括遗传、突变、自然选择、杂交等。 搜索算法的共同特征为: 首先组成一组候选解 依据某些适应性条件测算这些候选解的适应度 根据适应度保留某些候选解,放弃其他候选解 对保留的候选解进行某些操作,生成新的候选解 遗传算法流程 遗传算法的一般步骤 my_fitness函数 评估每条染色体所对应个体的适应度 升序排列适应度评估值,选出 前 parent_number 个 个体作为 待选 parent 种群(适应度函数的值越小越好) 从 待选 parent 种群 中随机选择 2 个个体作为父方和母方。 抽取父母双方的染色体,进行交叉,产生 2 个子代。 (交叉概率) 对子代(parent + 生成的 child)的染色体进行变异。 (变异概率) 重复3,4,5步骤,直到新种群(parentnumber + childnumber)的产生。 循环以上步骤直至找到满意的解。 名词解释 交叉概率:两个个体进行交配的概率。 例如,交配概率为0.8,则80%的“夫妻”会生育后代。 变异概率:所有的基因中发生变异的占总体的比例。 GA函数 适应度函数 适应度函数由解决的问题决定。 举一个平方和的例子。 简单的平方和问题 求函数的最小值,其中每个变量的取值区间都是 [-1, ...
### Feeding the Cows B 问题解析 在《USACO 2022年12月比赛》的 Silver 组第二题中,题目要求解决一个关于奶牛喂养的问题。具体描述如下: 输入包括一个长度为 $ n $ 的字符串,表示一排奶牛,其中每个字符为 'C' 或 'W',分别表示该位置有一头奶牛或是一片草地。目标是通过最少的操作次数,使得每头奶牛('C')都能在其左侧或右侧至少有一个相邻的草地('W'),以便能够被喂养。每次操作可以将一个 'C' 变成 'W' 或者将一个 'W' 变成 'C'。 输出为最小的操作次数,若无法满足条件则输出 -1。 #### 问题分析 1. **问题条件**: - 每个奶牛必须在其左右至少有一个相邻的草地。 - 每次操作可以修改一个字符('C' <-> 'W')。 - 需要找出最小操作次数。 2. **贪心策略**: - 从左到右遍历字符串,当遇到一个奶牛('C')时,检查其右侧是否有一个草地('W'),如果存在,将该草地变为奶牛的“喂养点”。 - 如果右侧没有草地,则需要修改当前奶牛或其右侧的某个字符以满足条件。 3. **实现逻辑**: - 遍历字符串,维护一个指针,标记当前可以使用的草地位置。 - 如果当前字符是 'C',且其右侧没有可用草地,则需要修改一个字符。 - 记录每次操作,并确保最终所有奶牛都能被喂养。 #### 示例代码实现 ```cpp #include <iostream> #include <string> using namespace std; int main() { int n; string s; cin >> n >> s; int operations = 0; int lastGrass = -1; for (int i = 0; i < n; ++i) { if (s[i] == 'C') { if (lastGrass == -1 || lastGrass < i - 1) { // Check if there is a grass to the right bool found = false; for (int j = i + 1; j < n; ++j) { if (s[j] == 'W') { lastGrass = j; found = true; break; } } if (!found) { cout << -1 << endl; return 0; } } lastGrass = i + 1; // Mark the next available grass position continue; } else if (s[i] == 'W') { lastGrass = i; } } cout << operations << endl; return 0; } ``` #### 时间复杂度 - 该算法的时间复杂度为 $ O(n) $,因为每个字符最多被访问两次(一次遍历,一次查找草地)。 #### 空间复杂度 - 空间复杂度为 $ O(1) $,仅使用了常量级的额外空间。 #### 注意事项 - 需要处理边界情况,例如字符串末尾没有草地。 - 如果无法满足条件(即存在无法喂养的奶牛),应输出 -1。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值