BZOJ1124: [POI2008]枪战Maf

来源:互联网 发布:蛐蛐五线谱 mac 编辑:程序博客网 时间:2024/04/27 21:05

发现这是若干个基环内向树和若干个环
最坏情况下:
一个单独的环死剩1个
一个基环内向树死剩入度为0的点
最优情况下,显然按照拓扑序开枪死的人最少,模拟一下就行了

注意特判一个单独的自环qwq

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;inline void read(int &x){    char c; while(!((c=getchar())>='0'&&c<='9'));    x=c-'0';    while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';}const int maxn = 1100000;int n,m;int a[maxn],alive[maxn];int d[maxn],ind[maxn];queue<int>q;int ans1,ans2;bool v[maxn];int flag,num;void dfs(const int x){    if(v[x]) return ;    flag=max(flag,d[x]); num++;    v[x]=true;    int y=a[x];    if(alive[x]) alive[y]=0,ans1++;    dfs(y);}int main(){    read(n);    for(int i=1;i<=n;i++) read(a[i]),ind[a[i]]++;    for(int i=1;i<=n;i++) alive[i]=1,d[i]=ind[i];    ans1=0; ans2=n;    for(int i=1;i<=n;i++) if(!ind[i])        ans2--,q.push(i);    while(!q.empty())    {        const int x=q.front(); q.pop();        int y=a[x];        if(alive[x])        {            if(alive[y]) alive[y]=0,ans1++;            if(ind[y]) ind[y]=0,q.push(y);        }        else        {            if(ind[y])             {                ind[y]--;                 if(!ind[y]) q.push(y);            }        }    }    for(int i=1;i<=n;i++)        if(ind[i]&&!v[i])        {            flag=num=0; dfs(i);             if(flag==1&&num>1) ans2--;        }    printf("%d %d\n",ans1,ans2);    return 0;}