zoukankan      html  css  js  c++  java
  • [JSOI2010]连通数[tarjan缩点]

    [JSOI2010] 连通数

    bzoj2208 luogu4306

    缩点完后用bitset来统计==

    按拓扑序来

    #include<bits/stdc++.h>
    using namespace std;
    #define Max(x,y) ((x)>(y)?(x):(y))
    #define Min(x,y) ((x)<(y)?(x):(y))
    const int N=2000+10,M=4000000+10,inf=0x3f3f3f3f;
    int n;
    char ss[N];
    bitset<N>f[N];
    template <class t>void rd(t &x){
        x=0;int w=0;char ch=0;
        while(!isdigit(ch)) w|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=w?-x:x;
    }
    
    int head[N],hd[N],tot=0,tt=0;
    struct edge{int v,nxt;}e[M],E[M];
    void Add(int u,int v){E[++tt]=(edge){v,hd[u]},hd[u]=tt;}
    void add(int u,int v){e[++tot]=(edge){v,head[u]},head[u]=tot;}
    
    int idx=0,Bcnt=0,dfn[N],low[N],bl[N],sz[N];
    stack<int>s;bool inst[N];
    void tarjan(int u){
        dfn[u]=low[u]=++idx,s.push(u),inst[u]=1;
        for(int i=head[u],v;i;i=e[i].nxt)
            if(!dfn[v=e[i].v]) tarjan(v),low[u]=Min(low[u],low[v]);
            else if(inst[v]&&dfn[v]<low[u]) low[u]=dfn[v];
        if(dfn[u]==low[u]){
            ++Bcnt;int v;
            do{
                v=s.top(),s.pop(),inst[v]=0,f[Bcnt].set(v);
                bl[v]=Bcnt,++sz[Bcnt];
            }while(u!=v);
        }
    }
    
    int Q[N],in[N];
    queue<int>q;
    void topsort(){
    	for(int i=1;i<=Bcnt;++i) if(!in[i]) q.push(i);
    	while(!q.empty()){
    		int u=q.front();
    		q.pop(),Q[++Q[0]]=u;
    		for(int i=hd[u],v;i;i=E[i].nxt)
    			if(!--in[v=E[i].v]) q.push(v);
    	}
    	for(int i=Q[0];i;--i)
    		for(int j=hd[Q[i]];j;j=E[j].nxt)
    			f[Q[i]]|=f[E[j].v];
    }
    
    int main(){
    	freopen("in.txt","r",stdin);
    	rd(n);
    	for(int i=1;i<=n;++i){
    		scanf("%s",ss+1);
    		for(int j=1;j<=n;++j)
    			if(ss[j]=='1') add(i,j);
    	}
    	for(int i=1;i<=n;++i)
    	if(!dfn[i]) tarjan(i);
    	for(int u=1,v;u<=n;++u)
    		for(int i=head[u];i;i=e[i].nxt)
    			if(bl[u]!=bl[v=e[i].v]) Add(bl[u],bl[v]),++in[bl[v]];
    	int ans=0;
    	topsort();
    	for(int i=1;i<=Bcnt;++i) ans+=f[i].count()*sz[i];
    	printf("%d",ans);
    	return 0;
    }
    
  • 相关阅读:
    SVN日常使用
    zabbix安装
    shell日常脚本(centos6)
    mysql故障记录
    PHP商品秒杀功能实现思路分析
    Redis
    PHP 实现实时通信一般有两种方式
    FTP DNS SMTP POP3 HTTP HTTPS DHCP DNS SNMP Telnet 端口号
    TCP/UDP/HTTP的区别和联系
    TCP 和 UDP 的区别
  • 原文地址:https://www.cnblogs.com/lxyyyy/p/11548366.html
Copyright © 2011-2022 走看看