zoukankan      html  css  js  c++  java
  • bzoj1124:[POI2008]枪战Maf

    传送门

    可以知道一共最多只有3种情况:基环树,环,自环
    先考虑最少杀死:
    首先发现入度为0的点一定能活下来,那么入度为0的点指向的人一定会死,他指向的人指向的人如果入度为0就一定能活下来(其实是不一定的,但是要保证死的人最少)
    这样就可以拓扑排序写一下了,剩下的就是环的情况了,能活下来的显然是(lfloor{size/2} floor)
    答案就是n-(拓扑排序找出的点)-环的情况活下来的人
    再考虑最多杀死:
    显然,入度为0的点一定能活,一个单独的环最少只能活下来1个人,而奇环树上的环最少能活下来0个人
    答案就是n-(入度为0的点)-环的情况活下来的人
    代码:

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    void read(int &x) {
    	char ch; bool ok;
    	for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    	for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
    }
    #define rg register
    const int maxn=1e6+10;
    int n,a[maxn],iin[maxn],in[maxn],q[maxn],tot,now;bool vis[maxn],used[maxn];
    int main()
    {
    	read(n);
    	for(rg int i=1;i<=n;i++)read(a[i]),in[a[i]]++,iin[a[i]]++;
    	for(rg int i=1;i<=n;i++)if(!in[i])q[++tot]=i,used[i]=1,now++;
    	for(int i=1;i<=tot;i++)
    	{
    		if(vis[a[q[i]]]||used[a[a[q[i]]]])continue;
    		if(!(--in[a[a[q[i]]]]))used[a[a[q[i]]]]=1,q[++tot]=a[a[q[i]]];
    		vis[a[q[i]]]=1;
    	}
    	for(rg int i=1;i<=n;i++)
    		if(in[i]>0&&!used[i]&&!vis[i])
    		{
    			bool flag=0;int sum=0,x=i;
    			while(!used[a[x]])flag|=(iin[x]>1),sum++,used[x]=1,x=a[x];
    			if(a[x]!=x)sum++,flag|=(iin[x]>1),used[x]=1;
    			tot+=sum/2;if(!flag&&a[x]!=x)now++;
    		}
    	printf("%d %d
    ",n-tot,n-now);
    }
    
  • 相关阅读:
    1093 Count PAT's(25 分)
    1089 Insert or Merge(25 分)
    1088 Rational Arithmetic(20 分)
    1081 Rational Sum(20 分)
    1069 The Black Hole of Numbers(20 分)
    1059 Prime Factors(25 分)
    1050 String Subtraction (20)
    根据生日计算员工年龄
    动态获取当前日期和时间
    对计数结果进行4舍5入
  • 原文地址:https://www.cnblogs.com/lcxer/p/10391177.html
Copyright © 2011-2022 走看看