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);
    }
    
  • 相关阅读:
    扩展域并查集经典题
    2010提高组-C]关押罪犯(扩展域并查集
    [2015普及组-D]推销员 思维que
    The 2019 Asia Nanchang First Round Online Programming Contest C(cf原题,线段树维护矩阵)
    Fire-Fighting Hero(多源最短路和单源最短路)
    The Preliminary Contest for ICPC Asia Xuzhou 2019
    Cow Routing(最短路spfa)
    hdu6582
    ACM_题目这么难,来局愉快的昆特牌吧
    ACM_水题你信吗
  • 原文地址:https://www.cnblogs.com/lcxer/p/10391177.html
Copyright © 2011-2022 走看看