bzoj2438: [中山市选2011]杀人游戏

感觉今天状态起飞了!!!之前留的坑一调就A了,舒服!!!

那么这题之前一看就觉得,假如一个人没人认识实际上他必须查一下,那么我第一次做的时候就把他抽象成了很多棵树,然后我只查树根,然后下面的每一层我都知道身份,那就没有生命之忧了。然后特判一下有一个人没人认识tata也不认识别人,就是自己独立出来的,那他最后留下来实际上不用查。

然后实际上这题怎么可能这么简单,肯定会构环的,那么就考虑强连通缩点,那么这题难就难在怎么判最后查剩一个人的情况了,那么具体怎么做呢?首先这个点入度肯定为0的,再者这个联通块肯定是只有一个点,不然还是需要问的,第三查他所能得知的点入度要>1,否则的话说明这个点必须通过当前这个点才能得知身份,还是需要查他。所以说这题细节还是很多的,搞得那时候感冒晕乎乎的。。。。

#include<cstdio>
#include<iostream> 
#include<cstring>
using namespace std;

int n,m;
struct node
{
    int x,y,next;
}a[310000],e[310000];int len,last[1100000],elen,elast[1100000];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
void eins(int x,int y)
{
    elen++;
    e[elen].x=x;e[elen].y=y;
    e[elen].next=elast[x];elast[x]=elen;
}
int id,dfn[1100000],low[1100000];
int top,sta[1100000];
int cnt,belong[1100000],size[1100000];
bool v[1100000];
void strong_unicom(int x)
{
    dfn[x]=low[x]=++id;
    sta[++top]=x;
    v[x]=true;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(dfn[y]==0)
        {
            strong_unicom(y);
            low[x]=min(low[x],low[y]);
        }
        else if(v[y]==true)
        {
            low[x]=min(low[x],dfn[y]);
        }
    }
    if(dfn[x]==low[x])
    {
        int i;cnt++;
        do
        {
            i=sta[top];top--;
            belong[i]=cnt;
            v[i]=false;
            size[cnt]++;
        }while(i!=x);
    }
}

int ru[1100000];
bool check(int x)
{
    if(size[x]!=1)return true;
    if(elast[x]==0)return false;
    for(int k=elast[x];k;k=e[k].next)
    {
        int y=e[k].y;
        if(ru[y]<=1)return true;
    }
    return false;
}
int main()
{
    int x,y;
    scanf("%d%d",&n,&m);
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        ins(x,y);
    }
    
        
    id=0;top=0;cnt=0;
    memset(dfn,0,sizeof(dfn));
    memset(v,false,sizeof(v));
    memset(size,0,sizeof(size));
    for(int i=1;i<=n;i++)
        if(dfn[i]==0)
            strong_unicom(i);
            
    memset(ru,0,sizeof(ru));
    elen=0;memset(elast,0,sizeof(elast));
    for(int i=1;i<=m;i++)
    {
        x=belong[a[i].x],y=belong[a[i].y];
        if(x!=y)
        {
            ru[y]++;
            eins(x,y);
        }
    }
    
    int sum=0;
    for(int i=1;i<=cnt;i++)
        if(ru[i]==0)sum++;
    for(int i=1;i<=cnt;i++)
        if(ru[i]==0)
            if(check(i)==false){sum--;break;}
            
    printf("%.6lf\n",1.0-double(sum)/double(n));
    return 0;
}

 

posted @ 2017-11-26 14:46  AKCqhzdy  阅读(265)  评论(0编辑  收藏  举报