T1 特工szp

【问题描述】

Byteotian 中央情报局 (BIA) 雇佣了许多特工. 他们每个人的工作就是监视另一名特工.
Byteasar 国王需要进行一次秘密行动,所以他要挑选尽量多的信得过的特工. 但是这项任务是如此的机密以至于所有参加行动的特工都必须至少被另一名没有参加任务的特工所监视(就是说如果某个特工参加了行动,那么原先监视他的那些特工中至少要有一个没有参加进行动). 给出监视任务的详情,要求计算最多能有多少个特工参与其中.

【输入格式】

第一行只有一个整数, n – 特工的总数, 2 <= n <= 1000000. 特工从 1 到 n编号. 接下来 n 行每行一个整数 ak 表示特工 k 将要监视特工 ak , 1 <= k <= n, 1<= ak <= n, ak <> k.

【输出格式】

打印一个数,最多能有多少特工参加入这个任务.

【样例输入】

6
2
3
l
3
6
5

【样例输出】

3

Solution

来源:POI

①基环内向树+dp

每个点只有一条出边,基环内向树

将内向树先做了f[x][0]代表这个点不选,f[x][1]代表这个点选.转移(y为x的儿子):f[x][0]+=max(f[y][0],f[y][1]),f[i][1]=max(1+f[i][0]+f[y][0]-max(f[y][0],f[y][1]),f[i][1]);

做环的时候先随意选一个点(我选的第一个)割环为链,就是把第一个和最后一个点分开.

记g[x][0]为x选的个数,g[x][1]为x不选的个数

枚举最后一个点的情况(l为首个,r为末个),

0时,g[q[l]][0]=f[q[r]][1]+f[q[l]][0],g[q[l]][1]=f[q[r]][1]+f[q[l]][1];

1时,g[q[l]][0]=f[q[r]][0]+f[q[l]][0],g[q[l]][1]=f[q[r]][0]+max(f[q[l]][0]+1,f[q[l]][1]?f[q[l]][1]:1);

然后O(n)扫一遍环g[q[i]][0]=max(g[q[i-1]][0],g[q[i-1]][1])+f[q[i]][0],g[q[i]][1]=max(max(g[q[i-1]][0],g[q[i-1]][1])+f[q[i]][1],max(f[q[i]][0]+1,f[q[i]][1])+g[q[i-1]][0]);

注意特判当枚举最后一个点选的时候,如果!f[q[r]][1]即它没有子树(内向树),那么这次答案只能为g[q[r-1]][0]+1 else 每次答案max(g[q[r-1]][0],g[q[r-1]][1])

②贪心+拓扑序

又是鬼boy光勋考场上写的鬼算法

贪心思想,内向树中如果一个点它的儿子中有白点(不选),那么他肯定要选,因为他不选的话仅仅只会创造出一个黑点(它爸),而它爸还不如变白让爷爷变黑,对答案只增不少.

(题解)证明:若点i确定为白色,a[i]染白色也只能提供一个黑点,故a[i]染黑色不会差;若所有指向i的点均为黑色,则i只能是白色。

从度为零的点开始按拓扑序跑,将他爸标为黑点,爷爷度数--,度数为零入队.这样子连环也可以切开.然后还剩下一些单环(没有内向树),ans+=size/2.

Code

// <szp.cpp> - Thu Oct  6 08:17:54 2016
// This file is made by YJinpeng,created by XuYike's black technology automatically.
// Copyright (C) 2016 ChangJun High School, Inc.
// I don't know what this program is. #include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#define MOD 1000000007
#define INF 1e9
#define IN inline
#define RG register
using namespace std;
typedef long long LL;
const int MAXN=;
inline int max(int &x,int &y) {return x>y?x:y;}
inline int min(int &x,int &y) {return x<y?x:y;}
inline int gi() {
register int w=,q=;register char ch=getchar();
while((ch<''||ch>'')&&ch!='-')ch=getchar();
if(ch=='-')q=,ch=getchar();
while(ch>=''&&ch<='')w=w*+ch-'',ch=getchar();
return q?-w:w;
}
int t;bool u[MAXN],k[MAXN];int f[MAXN][],g[MAXN][];
int fr[MAXN],to[MAXN],fa[MAXN],ne[MAXN],q[MAXN];
IN void add(int u,int v){
to[++t]=v;ne[t]=fr[u];fr[u]=t;
}
IN void dfs(int i){
k[i]=;
for(int j=fr[i],y;y=to[j],j;j=ne[j])
dfs(y),f[i][]+=max(f[y][],f[y][]);
for(int j=fr[i],y;y=to[j],j;j=ne[j])
f[i][]=max(+f[i][]+f[y][]-max(f[y][],f[y][]),f[i][]);
}
int work(int l,int r,bool ty){
g[q[r-]][]=g[q[r-]][]=;
if(ty){
g[q[l]][]=f[q[r]][]+f[q[l]][];
g[q[l]][]=f[q[r]][]+f[q[l]][];
}else{
g[q[l]][]=f[q[r]][]+f[q[l]][];
g[q[l]][]=f[q[r]][]+max(f[q[l]][]+,f[q[l]][]?f[q[l]][]:);
}
for(int i=l+;i<r;i++){
g[q[i]][]=max(g[q[i-]][],g[q[i-]][])+f[q[i]][];
g[q[i]][]=max(max(g[q[i-]][],g[q[i-]][])+f[q[i]][],max(f[q[i]][]+,f[q[i]][])+g[q[i-]][]);
}
if(ty&&!f[q[r]][])return g[q[r-]][]+;//this case=0
return max(g[q[r-]][],g[q[r-]][]);
}
int main()
{
freopen("szp.in","r",stdin);
freopen("szp.out","w",stdout);
int n=gi(),ans=;
for(int i=;i<=n;i++){
fa[i]=gi();add(fa[i],i);
}
while(){
int x,tot=,o;
for(x=;x<=n;x++)if(!k[x])break;
if(x==n+)break;u[q[tot=]=x]=;
while(!u[fa[x]])x=fa[x],u[q[++tot]=x]=;
x=fa[x];for(o=tot;o;o--)if(q[o]==x)break;
for(int i=;i<=tot;i++)u[q[i]]=;q[o-]=q[tot];
for(int i=o;i<=tot;i++){
k[q[i]]=;
for(int j=fr[q[i]],y;y=to[j],j;j=ne[j])
if(y!=q[i-])dfs(y),f[q[i]][]+=max(f[y][],f[y][]);
for(int j=fr[q[i]],y;y=to[j],j;j=ne[j])
if(y!=q[i-])f[q[i]][]=max(+f[q[i]][]+f[y][]-max(f[y][],f[y][]),f[q[i]][]);
}
ans+=max(work(o,tot,),work(o,tot,));
}
printf("%d",ans);
return ;
}

②xyk's

// <szp.cpp> - Thu Oct  6 08:07:12 2016
// This file is created by XuYike's black technology automatically.
// Copyright (C) 2015 ChangJun High School, Inc.
// I don't know what this program is. #include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
typedef long long lol;
int gi(){
int res=,fh=;char ch=getchar();
while((ch>''||ch<'')&&ch!='-')ch=getchar();
if(ch=='-')fh=-,ch=getchar();
while(ch>=''&&ch<='')res=res*+ch-'',ch=getchar();
return fh*res;
}
const int MAXN=;
const int INF=1e9;
int a[MAXN],d[MAXN];
bool vis[MAXN];
queue <int> q;
int main(){
freopen("szp.in","r",stdin);
freopen("szp.out","w",stdout);
int n=gi();
for(int i=;i<=n;i++){
a[i]=gi();
d[a[i]]++;
}
for(int i=;i<=n;i++)if(!d[i])q.push(i);
int ans=;
while(!q.empty()){
int x=q.front();q.pop();
vis[x]=;
if(vis[a[x]])continue;
vis[a[x]]=;
ans++;
if(!--d[a[a[x]]])q.push(a[a[x]]);
}
for(int i=;i<=n;i++){
if(vis[i])continue;
vis[i]=;int sz=;
for(int j=a[i];j!=i;j=a[j]){vis[j]=;sz++;}
ans+=sz>>;
}
printf("%d",ans);
return ;
}

【POI】T1 特工 szp的更多相关文章

  1. 10.6 Graph Test

    一套图论的练习题,各个方面都有挺好的 第一第二题有一定难度(来源POI),第三第四题比较水 但我并没考好 T1 特工 szp T2 洞穴 zaw T3 最短路 line T4 最小差异值 dvalue

  2. WinDbg调试命令汇总

    一. 1. !address eax 查看对应内存页的属性 2. vertarget 显示当前进程的大致信息 3 !peb 显示process Environment Block 4. lmvm 可以 ...

  3. ------- 软件调试——注销 QQ 过滤驱动设置的事件通知 CallBack (完)-------

    ---------------------------------------------------------------------------------- 本系列的最后一篇演示如何通过调试手 ...

  4. Windbg简明教程(转)

    Windbg是Microsoft公司免费调试器调试集合中的GUI的调试器,支持Source和Assembly两种模式的调试.Windbg不仅可以调试应用程序,还可以进行Kernel Debug(新版本 ...

  5. 【POJ】【3525】Most Distant Point from the Sea

    二分+计算几何/半平面交 半平面交的学习戳这里:http://blog.csdn.net/accry/article/details/6070621 然而这题是要二分长度r……用每条直线的距离为r的平 ...

  6. 51nod 1766 树上的最远点对(线段树)

    像树的直径一样,两个集合的最长路也是由两个集合内部的最长路的两个端点组成的,于是我们知道了两个集合的最长路,枚举一下两两端点算出答案就可以合并了,所以就可以用线段树维护一个区间里的最长路了. #inc ...

  7. Windbg脚本和扩展工具开篇

    好长一段时间没写文章了,最近一直忙于为项目的可调式性做一些脚本和扩展工具,鉴于对windbg强大威力的震撼,以及相对较少的资料,笔者决定写一系列关于如何开发Windbg脚本和扩展命令的文章,您的支持是 ...

  8. 【学习笔记】动态规划—各种 DP 优化

    [学习笔记]动态规划-各种 DP 优化 [大前言] 个人认为贪心,\(dp\) 是最难的,每次遇到题完全不知道该怎么办,看了题解后又瞬间恍然大悟(TAT).这篇文章也是花了我差不多一个月时间才全部完成 ...

  9. [POI 2004]SZP

    Description Byteotian 中央情报局 (BIA) 雇佣了许多特工. 他们每个人的工作就是监视另一名特工.Byteasar 国王需要进行一次秘密行动,所以他要挑选尽量多的信得过的特工. ...

随机推荐

  1. 记一次被面试的final问题

    ---- 前言 今天面试被问到了,我们都知道final修饰的东西是不可变的,那么是值不可变还是其地址不可变?一脸懵逼,回来查阅一番,总结一下 --- final与数据 在日常行为下,一般数据指的都是基 ...

  2. 零基础入门学习Python(27)--集合:在我的世界里,你就是唯一

    知识点 集合:set set和dict类似,也是一组key的集合,但不存储value.由于key不能重复,所以,在set中,没有重复的key. 集合中的元素的三个特征: 1)确定性(元素必须可hash ...

  3. LeetCode 188. Best Time to Buy and Sell Stock IV (stock problem)

    Say you have an array for which the ith element is the price of a given stock on day i. Design an al ...

  4. vscode调试angular2

    调试步骤: 1.安装nodejs 2.安装vscode 3.vscode安装debugger for chrome插件 4.选择调试->打开调试配置,选择chrome配置,打开lauch.jso ...

  5. STM32F407 正点原子 资料网址记录

    网络资源 资源下载: http://www.openedv.com/thread-13912-1-1.html (注意下载资料的版本!非常推荐腾讯视频,因为可以在线免费倍速播放.课件ppt可以单独下载 ...

  6. xcap发包工具的简单使用3(报文描述)

    之前详细介绍了如何构造以及发送报文,现在简单对报文描述一下 1.Ethernet MAC:填写报文目的mac和源mac地址 Vlan:支持单vlan,QinQ,如果有更多的vlan,请填写在“More ...

  7. 九度oj 题目1438:最小公倍数

    题目1438:最小公倍数 时间限制:1 秒 内存限制:128 兆 特殊判题:否 提交:2451 解决:2057 题目描述: 给定两个正整数,计算这两个数的最小公倍数. 输入: 输入包含多组测试数据,每 ...

  8. [BZOJ1264][AHOI2006]基因匹配Match(DP + 树状数组)

    传送门 有点类似LCS,可以把 a[i] 在 b 串中的位置用一个链式前向星串起来,由于链式前向星是从后往前遍历,所以可以直接搞. 状态转移方程 f[i] = max(f[j]) + 1 ( 1 &l ...

  9. 【ZJOI2017 Round1练习&BZOJ4774】D3T2 road(斯坦纳树,状压DP)

    题意: 对于边带权的无向图 G = (V, E),请选择一些边, 使得1<=i<=d,i号节点和 n − i + 1 号节点可以通过选中的边连通, 最小化选中的所有边的权值和. d< ...

  10. 「CodePlus 2017 11 月赛」大吉大利,晚上吃鸡!

    n<=50000,m<=50000的图,给s和t,问有多少点对$(a,b)$满足 嗯. 不会. 首先最短路DAG造出来,然后两个条件转述一下:条件一,$N_a$表示从s到t经过a的路径,$ ...