[POI 2008]Mafia
这题目写了我好长时间,但还是几乎(不要在意细节)一遍 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 也很好想嘛
似乎除了难写就没有难度了喵?
#include <cstdio>
#include <cstring>
const int size=;
const int inf=size; namespace IOspace
{
inline void assign() {freopen("isaac.in", "r", stdin); freopen("isaac.out", "w", stdout);}
inline void close() {fclose(stdin); fclose(stdout);}
inline int getint()
{
register int num=;
register char ch;
do ch=getchar(); while (ch<'' || ch>'');
do num=num*+ch-'', ch=getchar(); while (ch>='' && ch<='');
return num;
}
inline void putint(int num, char ch='\n')
{
char stack[];
register int top=;
if (num==) stack[top=]='';
for ( ;num;num/=) stack[++top]=num%+'';
for ( ;top;top--) putchar(stack[top]);
if (ch) putchar(ch);
}
} int n;
int g[size][];
int t, a[size];
int f[size], d[size];
int dp[size][];
bool vis[size], loop[size]; struct edge {int point; edge * next;};
edge MEM[size], * PORT=MEM;
edge * E[size];
inline edge * newedge(int _point, edge * _next)
{edge * ret=PORT++; ret->point=_point; ret->next=_next; return ret;} inline int min(int x, int y) {return x<y?x:y;}
inline int max(int x, int y) {return x>y?x:y;}
inline void add(int & x, int y) {if (x>=inf || y>=inf) x=inf; else x+=y;}
inline int search(int);
inline int find(int);
inline void bfs(int); int main()
{
int ans1=, ans2=; n=IOspace::getint();
for (int i=;i<=n;i++)
{
f[i]=IOspace::getint(), d[f[i]]++;
if (f[i]==i) ans2++, vis[i]=;
E[f[i]]=newedge(i, E[f[i]]);
} for (int i=;i<=n;i++) if (!d[i])
{
vis[i]=;
ans2+=search(i);
}
for (int i=;i<=n;i++) if (!vis[i])
{
vis[i]=;
ans2+=search(i);
} memset(vis, , sizeof(vis));
for (int i=;i<=n;i++) if (!vis[i])
{
vis[i]=;
ans1+=find(i);
} IOspace::putint(ans1, ' '); IOspace::putint(ans2); return ;
}
inline int search(int x)
{
int ret=;
for (x=f[x];!vis[x];x=f[x]) vis[x]=, ret++;
return ret;
}
inline void bfs(int x)
{
static int l, r, q[size]; l=r=;
for (q[r++]=x;l<r; )
{
int u=q[l++];
for (edge * i=E[u];i;i=i->next)
if (!loop[i->point])
{
vis[i->point]=;
q[r++]=i->point;
}
} for (int i=r-;i>=;i--)
if (E[q[i]]==NULL) dp[q[i]][]=inf;
else if (E[q[i]]->next==NULL && loop[E[q[i]]->point]) dp[q[i]][]=((E[q[i]]->point)==q[i])?:inf;
else
{
for (edge * j=E[q[i]];j;j=j->next)
if (!loop[j->point])
add(dp[q[i]][], dp[j->point][]);
for (edge * j=E[q[i]];j;j=j->next)
if (!loop[j->point])
add(dp[q[i]][], min(dp[j->point][], dp[j->point][]));
add(dp[q[i]][], );
}
}
inline int find(int x)
{
int ret=; vis[x]=;
for (x=f[x];!vis[x];x=f[x]) vis[x]=;
for (t=;!loop[x];x=f[x]) loop[a[t++]=x]=;
for (int i=;i<t;i++) bfs(a[i]);
if (t==) return dp[a[]][];
g[][]=dp[a[]][]; g[][]=inf;
for (int i=;i<t;i++)
{
g[i][]=min(g[i-][], g[i-][]);
add(g[i][], min(dp[a[i]][], dp[a[i]][]+));
g[i][]=g[i-][];
add(g[i][], dp[a[i]][]);
}
ret=g[t-][]; g[][]=dp[a[]][]; g[][]=inf;
for (int i=;i<t;i++)
{
g[i][]=min(g[i-][], g[i-][]);
add(g[i][], min(dp[a[i]][], dp[a[i]][]+));
g[i][]=g[i-][];
add(g[i][], dp[a[i]][]);
}
ret=min(ret, min(g[t-][], g[t-][])); g[][]=dp[a[]][]+; g[][]=inf;
for (int i=;i<t;i++)
{
g[i][]=min(g[i-][], g[i-][]);
add(g[i][], min(dp[a[i]][], dp[a[i]][]+));
g[i][]=g[i-][];
add(g[i][], dp[a[i]][]);
}
ret=min(ret, g[t-][]); return ret;
}
因为是考试时写的所以很长也是没办法的事系列
[POI 2008]Mafia的更多相关文章
- [POI 2008&洛谷P3467]PLA-Postering 题解(单调栈)
[POI 2008&洛谷P3467]PLA-Postering Description Byteburg市东边的建筑都是以旧结构形式建造的:建筑互相紧挨着,之间没有空间.它们共同形成了一条长长 ...
- [POI 2008][BZOJ 1132]Tro
这题我真是无能为力了 这题的做法还是挺简单的 枚举左下角的点做为原点,把其余点按极角排序 PS.是作为原点,如枚举到 k 时,对于所有 p[i] (包括p[k]) p[i]-=p[k] (此处为 ...
- bzoj 1112 poi 2008 砖块
这滞胀题调了两天了... 好愚蠢的错误啊... 其实这道题思维比较简单,就是利用treap进行维护(有人说线段树好写,表示treap真心很模板) 就是枚举所有长度为k的区间,查出中位数,计算代价即可. ...
- 解题:POI 2008 Subdivision of Kingdom
题面 还可以这么搜......学到了(PoPoQQQ orz) 我们最朴素的做法是枚举所有状态(当然可以剪,剪完最终实际状态量也是$C_{26}^{13}$的),然后每次$O(n)$扫一遍判断,大概会 ...
- 解题:POI 2008 Plot purchase
题面 原来看过然后没做,结果板板把这道题改了改考掉了,血亏=.= 首先看看有没有符合条件的点.如果没有开始寻找解,先把所有的大于$2*k$的点设为坏点,然后求最大子矩形,只要一个最大子矩形的权值和超过 ...
- 解题:POI 2008 Station
题面 水水的换根裸题,不过以前还真没做过换根的题 换根的思想就是在DFS中利用树的信息更新出当前点为根时的信息,具体来说一般是考虑子树外和子树内两部分 每个点的答案$ans$就是$ans[fa]+n- ...
- [BZOJ 1124][POI 2008] 枪战 Maf
1124: [POI2008]枪战Maf Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 659 Solved: 259[Submit][Status ...
- loj10104 [POI 2008]Blockade
传送门 分析 我们知道对于一个割点,我们如果去掉它就会使原来的图被分为若干块,则这是我们将所有块包含的点的个数两两相乘即可,而如果不是割点则对于图的连通性没有影响.注意在最后要加上2*(n-1)表示去 ...
- [POI 2008] BLO
[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1123 [算法] 首先,如果一个点不是割点,那么,去掉该点后不连通的有序点对就为 : ...
随机推荐
- 免费获得NOD32 半年、1年 激活码-14.08.12到期
地址: http://nod32.ruanmei.com/ 活动时间: 2014年8月6日 - 8月12日(全部送完将提前终止). 活动规则: 1.每台电脑限领1枚NOD32激活码: 2.领到的NOD ...
- python解无忧公主的数学时间097.py
python解无忧公主的数学时间097.py """ python解无忧公主的数学时间097.py codegay 2016年3月30日 00:17:26 http:// ...
- ThinkPHP查询数据与CURD
一.创建连接 在配置文件中使用如下配置: /* 数据库设置 */ 'DB_TYPE' => 'mysql', // 数据库类型 'DB_HOST' => 'localhost', // 服 ...
- HTML--2图片热点,网页划区,拼接
图片热点: 规划出图片上的一个区域,可以做出超链接,直接点击图片区域就可以完成跳转的效果. 示例: 网页划区: 在一个网页里,规划出一个区域用来展示另一个网页的内容. 示例: 网页的拼接: 在一个网络 ...
- EF学习笔记(一)
EF(EntityFramwork)实体框架:主要是将实体类(EntityClass)和数据表(Table)进行映射(Map). EF核心对象: DbContext (数据访问核心对象) ...
- poj1458
//Accepted 4112 KB 16 ms //最长公共子串 #include <cstdio> #include <cstring> #include <iost ...
- POJ 1185 炮兵阵地(经典的状态压缩DP)
题意:中文题. 思路,经典的状态压缩题目. 由于列长比较小,我们可以以行为阶段用状态压缩来做. 由于攻击只占两个格,这样从行的角度看,第i行的炮兵只与前i-1和前i-2行有关系.这样如果用j,k,l分 ...
- GeekPwn2015胸卡ESP8266 12E串口调试
相信今年参加GeekPwn活动的很多同学都获得了一枚GeekPwn的胸牌,为方便大家对胸牌进行一些调试和破解,这里分享一些关于这枚胸牌的一些信息 :)如发现文章之中有错误之处,欢迎大家斧正! 0×00 ...
- 如何在ubuntu 12.04 中安装经典的 GNOME桌面
这次介绍的是如何在ubuntu 12.04 中安装经典的 GNOME桌面,默认的 Ubuntu 12.04 默认unity桌面,一些用户不喜欢 Unity 桌面,所以想找回昔日的经典Gnome桌面. ...
- SQL基础2
create database fuxi --创建一个名为“fuxi”的数据库go --连接语句use fuxi --使用名为“fuxi”的数据库gocreat ...