• UVALive


    题面

    点双杀我。

    一年多没写点双竟幼稚的以为栈里存的是点,awsl。

    具体题解参考刘汝佳的蓝书(滑稽),这里提醒几个细节:

        1.这样多组数据的,在时间允许的情况下尽量要把所有数组和vector什么的都清空,除非你特别特别特别确定哪些不用清空。

        2.割点是在>=2个点双中的,所以 每次判断一个点双是不是二分图时,一定要先把所有点双内的点标记一下tag,否则割点只会指向其中一个点双。

        3.点双栈里存的是边啦,不是点。。。。 顺便请注意一下,求点双,边双,scc的三种tarjan算法的区别。

    #include<cstdio>
    #include<vector>
    #include<stack>
    #include<cctype>
    #define ll long long
    using namespace std;
    #define pb push_back
    const int N=1005; 
    
    struct edge{ int x,y;};
    stack<edge> s;
    vector<int> g[N],lt[N];
    int n,m,k,dc,dfn[N],low[N];
    int v[N],col[N],now;
    bool cc[N][N],a[N];
    
    inline int read(){
        int x=0; char ch=getchar();
        for(;!isdigit(ch);ch=getchar());
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
        return x;
    }
    
    inline void init(){
    	fill(a+1,a+n+1,0);
    	fill(dfn+1,dfn+n+1,0),dc=0;
    	for(int i=1;i<=k;i++) lt[i].clear();
    	for(int i=1;i<=n;i++){
    	    g[i].clear();
    	    fill(cc[i]+1,cc[i]+n+1,0);
    	}
    	while(!s.empty()) s.pop();
    }
    
    void dfs(int x,int fa){
    	dfn[x]=low[x]=++dc;
    	
    	for(int i:g[x]) if(i!=fa)
    	    if(!dfn[i]){
    	    	s.push((edge){x,i}),dfs(i,x),low[x]=min(low[x],low[i]);
    	    	if(low[i]>=dfn[x]){
    	    		k++;
    	    		for(edge e;;){
    	    			e=s.top(),s.pop();
    	    			if(v[e.x]!=k) v[e.x]=k,lt[k].pb(e.x);
    	    			if(v[e.y]!=k) v[e.y]=k,lt[k].pb(e.y);
    					if(e.x==x&&e.y==i) break;	    			
    				}
    			}
    		}
    		else low[x]=min(low[x],dfn[i]);
    }
    
    bool bc(int x,int cl){
    	col[x]=cl;
    	for(int i:g[x]) if(v[i]==now)
    	    if(col[i]==cl) return 0;
    	    else if(!col[i]) if(!bc(i,cl^3)) return 0;
    	return 1;
    }
    
    inline void solve(){
    	for(int U,V;m;m--)
    		U=read(),V=read(),cc[U][V]=cc[V][U]=1;
    	for(int i=1;i<=n;i++)
    	    for(int j=i+1;j<=n;j++) if(!cc[i][j]) g[i].pb(j),g[j].pb(i);
    	
    	for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i,0);
    	
    	for(now=1;now<=k;now++){
    		for(int i:lt[now]) col[i]=0,v[i]=now;
    		if(!bc(lt[now][0],1)) for(int i:lt[now]) a[i]=1;
    	}
    	
    	int ans=0;
    	for(int i=1;i<=n;i++) ans+=!a[i];
    	printf("%d
    ",ans);
    }
    
    int main(){
    	while(scanf("%d%d",&n,&m)==2&&n&&m){
    		init();
    		solve();
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    Dockerfile基于centos镜像编译安装httpd
    Dockerfile基于centos镜像编译安装nginx
    Dockerfile介绍和常用指令
    Docker存储卷
    正则表达式
    Sed与Awk
    Shell函数
    Shell脚本基础
    Autofs
    Podman
  • 原文地址:https://www.cnblogs.com/JYYHH/p/11286591.html
Copyright © 2020-2023  润新知