这题目写了我好长时间,但还是几乎(不要在意细节)一遍 A 了喵~

据说有代码奇短的,Orz 思路巧妙的大爷

想我这种 Brute Force 写写的傻 X 真是代码量飞起来了耶,喵~

如果把每个人看成点,每个人要 kill 的人向此人连出一条有向边,那么每个点仅有一条出边和一条入边

经验告诉我们,这就是 环+内向图 的节奏

经验又告诉我,处理这种图要么先暴力搞环,再搞挂在环上的树。要么先搞树,再弄环。

此题显然是后者

环+内向图只需要用 bfs 就可以搞出来了,看到写 tarjan 的真是 Orz

弄出 环 和 树 后,先在树上跑 dp,用 dp[u][0] 表示如果 u 最后被 kill 了,那么以 u 为根子树最少要死几人, dp[u][1] 是 u 存活下来的情况

这是普及组难度的树形 dp 吧喵~

再在环上跑 dp ,我们先破环为链,则有3种情况 (我们令在首的人为 A , 在尾的人为 B)

1. A君 最后活着,那 B君 一定被 kill 了

2. A君 最后被 kill 了,B君 存活了或也被 kill 了

3. A君 存活了下来,B君 也存活了下来,然后 B君 kill A君

三种情况要分类讨论

中间过程的状态转移和以上三种情况类似,无非就是讨论 i 君 和 i+1 君 的是否被 kill 的关系  (妈妈说,某个字打出来是不好的喵~)

被 kill 有两种可能:1.被自己的子树中的某君 kill 了  2.被环上的某君 kill 了

这个 dp 也很好想嘛

似乎除了难写就没有难度了喵?

  1. #include <cstdio>
  2. #include <cstring>
  3. const int size=;
  4. const int inf=size;
  5.  
  6. namespace IOspace
  7. {
  8. inline void assign() {freopen("isaac.in", "r", stdin); freopen("isaac.out", "w", stdout);}
  9. inline void close() {fclose(stdin); fclose(stdout);}
  10. inline int getint()
  11. {
  12. register int num=;
  13. register char ch;
  14. do ch=getchar(); while (ch<'' || ch>'');
  15. do num=num*+ch-'', ch=getchar(); while (ch>='' && ch<='');
  16. return num;
  17. }
  18. inline void putint(int num, char ch='\n')
  19. {
  20. char stack[];
  21. register int top=;
  22. if (num==) stack[top=]='';
  23. for ( ;num;num/=) stack[++top]=num%+'';
  24. for ( ;top;top--) putchar(stack[top]);
  25. if (ch) putchar(ch);
  26. }
  27. }
  28.  
  29. int n;
  30. int g[size][];
  31. int t, a[size];
  32. int f[size], d[size];
  33. int dp[size][];
  34. bool vis[size], loop[size];
  35.  
  36. struct edge {int point; edge * next;};
  37. edge MEM[size], * PORT=MEM;
  38. edge * E[size];
  39. inline edge * newedge(int _point, edge * _next)
  40. {edge * ret=PORT++; ret->point=_point; ret->next=_next; return ret;}
  41.  
  42. inline int min(int x, int y) {return x<y?x:y;}
  43. inline int max(int x, int y) {return x>y?x:y;}
  44. inline void add(int & x, int y) {if (x>=inf || y>=inf) x=inf; else x+=y;}
  45. inline int search(int);
  46. inline int find(int);
  47. inline void bfs(int);
  48.  
  49. int main()
  50. {
  51. int ans1=, ans2=;
  52.  
  53. n=IOspace::getint();
  54. for (int i=;i<=n;i++)
  55. {
  56. f[i]=IOspace::getint(), d[f[i]]++;
  57. if (f[i]==i) ans2++, vis[i]=;
  58. E[f[i]]=newedge(i, E[f[i]]);
  59. }
  60.  
  61. for (int i=;i<=n;i++) if (!d[i])
  62. {
  63. vis[i]=;
  64. ans2+=search(i);
  65. }
  66. for (int i=;i<=n;i++) if (!vis[i])
  67. {
  68. vis[i]=;
  69. ans2+=search(i);
  70. }
  71.  
  72. memset(vis, , sizeof(vis));
  73. for (int i=;i<=n;i++) if (!vis[i])
  74. {
  75. vis[i]=;
  76. ans1+=find(i);
  77. }
  78.  
  79. IOspace::putint(ans1, ' '); IOspace::putint(ans2);
  80.  
  81. return ;
  82. }
  83. inline int search(int x)
  84. {
  85. int ret=;
  86. for (x=f[x];!vis[x];x=f[x]) vis[x]=, ret++;
  87. return ret;
  88. }
  89. inline void bfs(int x)
  90. {
  91. static int l, r, q[size];
  92.  
  93. l=r=;
  94. for (q[r++]=x;l<r; )
  95. {
  96. int u=q[l++];
  97. for (edge * i=E[u];i;i=i->next)
  98. if (!loop[i->point])
  99. {
  100. vis[i->point]=;
  101. q[r++]=i->point;
  102. }
  103. }
  104.  
  105. for (int i=r-;i>=;i--)
  106. if (E[q[i]]==NULL) dp[q[i]][]=inf;
  107. else if (E[q[i]]->next==NULL && loop[E[q[i]]->point]) dp[q[i]][]=((E[q[i]]->point)==q[i])?:inf;
  108. else
  109. {
  110. for (edge * j=E[q[i]];j;j=j->next)
  111. if (!loop[j->point])
  112. add(dp[q[i]][], dp[j->point][]);
  113. for (edge * j=E[q[i]];j;j=j->next)
  114. if (!loop[j->point])
  115. add(dp[q[i]][], min(dp[j->point][], dp[j->point][]));
  116. add(dp[q[i]][], );
  117. }
  118. }
  119. inline int find(int x)
  120. {
  121. int ret=;
  122.  
  123. vis[x]=;
  124. for (x=f[x];!vis[x];x=f[x]) vis[x]=;
  125. for (t=;!loop[x];x=f[x]) loop[a[t++]=x]=;
  126. for (int i=;i<t;i++) bfs(a[i]);
  127. if (t==) return dp[a[]][];
  128. g[][]=dp[a[]][]; g[][]=inf;
  129. for (int i=;i<t;i++)
  130. {
  131. g[i][]=min(g[i-][], g[i-][]);
  132. add(g[i][], min(dp[a[i]][], dp[a[i]][]+));
  133. g[i][]=g[i-][];
  134. add(g[i][], dp[a[i]][]);
  135. }
  136. ret=g[t-][];
  137.  
  138. g[][]=dp[a[]][]; g[][]=inf;
  139. for (int i=;i<t;i++)
  140. {
  141. g[i][]=min(g[i-][], g[i-][]);
  142. add(g[i][], min(dp[a[i]][], dp[a[i]][]+));
  143. g[i][]=g[i-][];
  144. add(g[i][], dp[a[i]][]);
  145. }
  146. ret=min(ret, min(g[t-][], g[t-][]));
  147.  
  148. g[][]=dp[a[]][]+; g[][]=inf;
  149. for (int i=;i<t;i++)
  150. {
  151. g[i][]=min(g[i-][], g[i-][]);
  152. add(g[i][], min(dp[a[i]][], dp[a[i]][]+));
  153. g[i][]=g[i-][];
  154. add(g[i][], dp[a[i]][]);
  155. }
  156. ret=min(ret, g[t-][]);
  157.  
  158. return ret;
  159. }

因为是考试时写的所以很长也是没办法的事系列

[POI 2008]Mafia的更多相关文章

  1. [POI 2008&洛谷P3467]PLA-Postering 题解(单调栈)

    [POI 2008&洛谷P3467]PLA-Postering Description Byteburg市东边的建筑都是以旧结构形式建造的:建筑互相紧挨着,之间没有空间.它们共同形成了一条长长 ...

  2. [POI 2008][BZOJ 1132]Tro

    这题我真是无能为力了 这题的做法还是挺简单的 枚举左下角的点做为原点,把其余点按极角排序    PS.是作为原点,如枚举到 k 时,对于所有 p[i] (包括p[k]) p[i]-=p[k] (此处为 ...

  3. bzoj 1112 poi 2008 砖块

    这滞胀题调了两天了... 好愚蠢的错误啊... 其实这道题思维比较简单,就是利用treap进行维护(有人说线段树好写,表示treap真心很模板) 就是枚举所有长度为k的区间,查出中位数,计算代价即可. ...

  4. 解题:POI 2008 Subdivision of Kingdom

    题面 还可以这么搜......学到了(PoPoQQQ orz) 我们最朴素的做法是枚举所有状态(当然可以剪,剪完最终实际状态量也是$C_{26}^{13}$的),然后每次$O(n)$扫一遍判断,大概会 ...

  5. 解题:POI 2008 Plot purchase

    题面 原来看过然后没做,结果板板把这道题改了改考掉了,血亏=.= 首先看看有没有符合条件的点.如果没有开始寻找解,先把所有的大于$2*k$的点设为坏点,然后求最大子矩形,只要一个最大子矩形的权值和超过 ...

  6. 解题:POI 2008 Station

    题面 水水的换根裸题,不过以前还真没做过换根的题 换根的思想就是在DFS中利用树的信息更新出当前点为根时的信息,具体来说一般是考虑子树外和子树内两部分 每个点的答案$ans$就是$ans[fa]+n- ...

  7. [BZOJ 1124][POI 2008] 枪战 Maf

    1124: [POI2008]枪战Maf Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 659  Solved: 259[Submit][Status ...

  8. loj10104 [POI 2008]Blockade

    传送门 分析 我们知道对于一个割点,我们如果去掉它就会使原来的图被分为若干块,则这是我们将所有块包含的点的个数两两相乘即可,而如果不是割点则对于图的连通性没有影响.注意在最后要加上2*(n-1)表示去 ...

  9. [POI 2008] BLO

    [题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1123 [算法] 首先,如果一个点不是割点,那么,去掉该点后不连通的有序点对就为 : ...

随机推荐

  1. 隐藏与显示:display/visibility/visible区别

    说到标签的隐藏,你们会用到什么呢?display?visibility?还是服务器控件的visible? 显然,这三者都能起到隐藏与显示的效果,但是用途确完全不一样,请看用法与区别: <div ...

  2. bjui简单了解

    bjui官网:http://demo.b-jui.com/ 其他的我就不是很了解,恶心.

  3. 使用Wireshark捕捉USB通信数据

    USB,是英文Universal Serial Bus(通用串行总线)的缩写,而其中文简称为“通串线”,是一个外部总线标准,用于规范电脑与外部设备的连接和通讯.USB接口支持设备的即插即用和热插拔功能 ...

  4. 在VS2010 中兼容Qt4和Qt5

    1,同时安装Qt4和Qt5 Qt_add,然后在 2. 如果之前的项目使用Qt4编写的,如果新添加新的类和ui的话,一定要选择Qt Add_in 1.1.11,不然就无法生成moc文件,随便选择 Ch ...

  5. js 检测 flash插件以及版本号 通用所有浏览器

    var fls = flashChecker(); if (fls.h) { if (fls.v < parseFloat('8.0')) { alert("您当前的flash pla ...

  6. bootstrap菜单完美解决---原创

    由于bootstrap的各方优点,偶的“点金项目细化分包管理平台”决定采用它.但在使用中遇到了一些问题,比如菜单的问题,这个菜单是用的一个JQuery的一个效果,点击后,所点击的链接处的class要加 ...

  7. More on Conditions - To Compare -Comparing Sequences and Other Types

    The conditions used in while and if statements can contain any operators, not just comparisons. The ...

  8. Drools规则文件结构说明

    一.规则文件构成 package(规则文件所在包) import(导入java包) global(规则文件中的"全局变量") function(函数) query(查找) rule ...

  9. FATE_完全背包

    ps:原来用新浪,可是代码的排版不是很好,所以用博客园啦,先容许我把从八月份开始的代码搬过来,从这里重新出发,希望这里可以一直见证我的成长. Time Limit: 2000/1000 MS (Jav ...

  10. C#导入、导出功能

    //导出功能 protected void btnExport(object sender, EventArgs e) { //用来打开下载窗口 string fileName = "中心联 ...