zoukankan      html  css  js  c++  java
  • BZOJ1124 [POI2008]枪战Maf[贪心(证明未完成)+拓扑排序]

    吐槽:扣了几个小时,大致思路是有了,但是贪心的证明就是不会,

    死磕了很长时间,不想想了,结果码代码又不会码。。

    深深体会到自己码力很差,写很多行还没写对,最后别人代码全一二十行,要哭了


    以下可能是个人口胡瞎扯:首先n个点,每个点一个出边,所以这个图可能是有很多连通块,具体有以下几种形态:

    • 内向基环树
    • 树上有一个点套一个自环

    这三种构成森林。

    先看最多死多少人。

    • 环的话是$siz-1$
    • 内向基环树只有树那部分的叶子(无入度)可以存活。画图举例辅助理解。
    • 树上带自环:同上

    再看很烦人的最少死多少人

    • 环:$ lfloor frac{n+1}{2} floor$
    • 内向基环树:拓扑排序,将入度为0的全加队里,一直这样处理,把死掉的点和开过枪的点删掉。
    • 树带自环:同上

    然后拓扑处理后上面三种形态的变化情况:

    • 环:不变
    • 内向基环树:可能剩下一个环,或者因为被破坏而啥都不剩
    • 树:可能剩下一个自环或无

    然后至于为什么要做拓扑排序,这是一个贪心,我没有办法严谨证明。。哭。

    首先对于树,肯定是从叶子开始把父亲全杀死,然后父亲的父亲是活的,继续向上开枪......这样比其他顺序是更优的。

    环的话也同理。而内向基环树我就不会证了。如果环上挂一个树,可以发现树根杀不杀死环上的点对于环上的点答案是无影响的。

    所以只看树的部分,也就是拓排。那一个环上挂很多个树呢?这辈子我一定会把他证出来的。

    总之就是先拓扑排序附带统计ans,然后只会剩下环和自环,然后再在这些环里处理答案。

    其实code我是厚颜无耻抄的。。自己写的实在搞不下去了。。今年破格抄一次code,到年尾再也不抄了

    付下这位神仙的题解:BZOJ1124: [POI2008]枪战Maf。感谢指导。侵删。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define dbg(x) cerr << #x << " = " << x <<endl
     8 using namespace std;
     9 typedef long long ll;
    10 typedef double db;
    11 typedef pair<int,int> pii;
    12 template<typename T>inline T _min(T A,T B){return A<B?A:B;}
    13 template<typename T>inline T _max(T A,T B){return A>B?A:B;}
    14 template<typename T>inline char MIN(T&A,T B){return A>B?(A=B,1):0;}
    15 template<typename T>inline char MAX(T&A,T B){return A<B?(A=B,1):0;}
    16 template<typename T>inline void _swap(T&A,T&B){A^=B^=A^=B;}
    17 template<typename T>inline T read(T&x){
    18     x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1;
    19     while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x;
    20 }
    21 const int N=1e6+7;
    22 int to[N],ind[N];
    23 int n,maxlive,minlive;
    24 int q[N],dead[N],cir[N];
    25 
    26 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout);
    27     read(n);
    28     for(register int i=1;i<=n;++i)read(to[i]),++ind[to[i]];
    29     for(register int i=1;i<=n;++i)if(!ind[i])++minlive,q[++maxlive]=i;
    30     for(register int l=1;l<=maxlive;++l){
    31         int y=to[q[l]];
    32         if(dead[y])continue;
    33         dead[y]=1,cir[to[y]]=1;
    34         if(!(--ind[to[y]]))q[++maxlive]=to[y];
    35     }
    36     for(register int i=1;i<=n;++i)if(!dead[i]&&ind[i]){
    37         int siz=0,p=0;
    38         for(register int j=i;!dead[j];j=to[j])dead[j]=1,++siz,p|=cir[j];
    39         if(!p&&(siz>1))++minlive;
    40         maxlive+=siz/2;
    41     }
    42     return printf("%d %d
    ",n-maxlive,n-minlive),0;
    43 }
    View Code

    我以后会来补证明的。

    人类的本质是鸽子

  • 相关阅读:
    CodeIgniter框架对数据库查询结果进行统计
    PHP的内存回收(GC)
    使用ajax请求后端程序时,关于目标程序路径问题
    JavaScript中的各种X,Y,Width,Height
    Qt编写气体安全管理系统7-设备监控
    Qt编写气体安全管理系统6-地图监控
    Qt编写气体安全管理系统5-数据监控
    Qt编写气体安全管理系统4-通信协议
    Qt编写气体安全管理系统3-用户模块
    Qt编写气体安全管理系统2-界面框架
  • 原文地址:https://www.cnblogs.com/saigyouji-yuyuko/p/11454974.html
Copyright © 2011-2022 走看看