现在的位置: 首页 > 综合 > 正文

【bzoj 1124】: [POI2008]枪战Maf

2017年04月23日 ⁄ 综合 ⁄ 共 2151字 ⁄ 字号 评论关闭

1124: [POI2008]枪战Maf

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 335  Solved: 130
[Submit][Status]

Description

有n个人,每个人手里有一把手枪。一开始所有人都选定一个人瞄准(有可能瞄准自己)。然后他们按某个顺序开枪,且任意时刻只有一个人开枪。因此,对于不同的开枪顺序,最后死的人也不同。

Input

输入n人数<1000000 每个人的aim

Output

你要求最后死亡数目的最小和最大可能

Sample Input

8

2 3 2 2 6 7 8 5

Sample Output

3 5

看网上的代码,理出来的思路,代码和网上的不一样,我用的栈来维护

虽然AC了,但还是有些不明白的地方

得到的图一定是一条条链指向一个环或者没有环

最多就让入度为0的都活着,一遍dfs,记录vis
剩下的没有vis的一定是环
剩下的每个环只剩一个

有可能原本有环,全都死亡

环一定是独立的环

最少:
首先考虑入度为0的点
他指向的一定先死,反正早晚都要死,晚死不如早死,
晚死他还多打死几个(这个不严密,感觉有漏洞),
他死了之后更新入度,重复这个过程
剩下的也是环的处理
偶数环打死一半
奇数环打死一半(上取整)

//#define _TEST _TEST
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <stack>
using namespace std;
/************************************************
Code By willinglive
************************************************/
/////////////////////////////////////////////////
#define rep(i,l,r) for(int i=l,___t=(r);i<=___t;i++)
#define per(i,r,l) for(int i=r,___t=(l);i>=___t;i--)
#define MS(arr,x) memset(arr,x,sizeof(arr))
#define LL long long
#define INE(i,u,e) for(int i=head[u];~i;i=e[i].next)
/////////////////////////////////////////////////
const int N=1000010;
int n;
int point[N];
int ind[N];

bool vis[N];
int ans1;
int t;
stack<int>s;
/////////////////////////////////////////////////
void dfs1(int u)
{
    vis[u]=1;
    t++;
    if(!vis[point[u]]) dfs1(point[u]);
}

void dfs2(int u,bool kill)
{
    vis[u]=1;
    if(kill) ans1++;
    if(kill && --ind[point[u]]==0) s.push(point[u]);
    if(!kill && !vis[point[u]]) dfs2(point[u],!kill);
}
/////////////////////////////////////////////////
void input()
{
    scanf("%d",&n);
    rep(i,1,n) scanf("%d",&point[i]),ind[point[i]]++;
}
void solve()
{
    ///////////////////init///////////////////
    int ans2=0;
    ////////////////calculate////////////////
    rep(i,1,n) if(ind[i]==0)
    {
        dfs1(i);
        ans2++;
    }
    rep(i,1,n) if(point[i]!=i && !vis[i])
    {
        dfs1(i);
        ans2++;
    }
    ans2=n-ans2;
    MS(vis,0);
    rep(i,1,n)
    {
        if(ind[i]==0) s.push(i);
    }
    while(!s.empty())
    {
        int u=s.top(); s.pop();
        dfs2(u,0);
    }
    rep(i,1,n)
    {
        if(!vis[i])
        {
            t=0;
            dfs1(i);
            ans1+=(t+1)/2;
        }
    }
    /////////////////output/////////////////
    printf("%d %d\n",ans1,ans2);
}
/////////////////////////////////////////////////
int main()
{
    #ifndef _TEST
    freopen("std.in","r",stdin); freopen("std.out","w",stdout);
    #endif
    input();
    solve();
    #ifdef _TEST
    for(;;);
    #endif
    return 0;
}

抱歉!评论已关闭.