zoukankan      html  css  js  c++  java
  • #Tarjan,拓扑排序#洛谷 3436 [POI2006]PRO-Professor Szu

    题目


    分析

    考虑有向图缩点然后拓扑排序,
    最恶心的地方是这题有自环,
    一旦存在自环就意味着答案一定超过阈值
    其实更难过的是Tarjan大小写写错没有发现qwq


    代码

    #include <cstdio>
    #include <cctype>
    #include <stack>
    #include <queue>
    #define rr register
    using namespace std;
    const int N=1000011;
    stack<int>stac; queue<int>q;
    struct node{int y,next;}e[N],E[N];
    int dfn[N],low[N],v[N],col[N],siz[N],m,ans,Ans;
    int deg[N],n,et,Et,cnt,tot,as[N],hs[N],dp[N];
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline signed min(int a,int b){return a<b?a:b;}
    inline void tarjan(int x){
    	dfn[x]=low[x]=++tot,
    	v[x]=1,stac.push(x);
    	for (rr int i=hs[x];i;i=E[i].next)
    	if (!dfn[E[i].y]){
    		tarjan(E[i].y);
    		low[x]=min(low[x],low[E[i].y]); 
    	}else if (v[E[i].y])
    	    low[x]=min(low[x],dfn[E[i].y]);
    	if (dfn[x]==low[x]){
    		rr int y; ++cnt;
    		do{
    			y=stac.top(); stac.pop();
    			col[y]=cnt,++siz[cnt],v[y]=0;
    		}while (x^y);
    	}
    }
    signed main(){
    	n=iut()+1,m=iut();
    	for (rr int i=1;i<=m;++i){
    		rr int y=iut(),x=iut();
    		E[++Et]=(node){y,hs[x]},hs[x]=Et;
    	}
    	for (rr int i=1;i<=n;++i)
    	    if (!dfn[i]) tarjan(i);
    	for (rr int i=1;i<=n;++i)
    	for (rr int j=hs[i];j;j=E[j].next)
    	if (i==E[j].y) ++siz[col[i]];
    	else if (col[i]^col[E[j].y]){
    		e[++et]=(node){col[E[j].y],as[col[i]]},
    		as[col[i]]=et,++deg[col[E[j].y]];
    	}
    	for (rr int i=1;i<=cnt;++i)
    	    if (!deg[i]) q.push(i);
    	dp[col[n]]=1,v[col[n]]=1;
    	while (!q.empty()){
    		rr int x=q.front(); q.pop();
    		for (rr int i=as[x];i;i=e[i].next){
    			if (!(--deg[e[i].y])) q.push(e[i].y);
    			if (v[x]) v[e[i].y]=1; dp[e[i].y]+=dp[x];
    			if (siz[e[i].y]>1&&v[e[i].y]) dp[e[i].y]=36501;
    			if (dp[e[i].y]>36501) dp[e[i].y]=36501;
    		}
    	}
    	for (rr int i=1;i<=cnt;++i)
    	    if (v[i]&&ans<dp[i]) ans=dp[i];
    	if (ans==36501) printf("zawsze
    ");
    	    else printf("%d
    ",ans);
    	for (rr int i=1;i<=n;++i)
    	    if (v[col[i]]&&ans==dp[col[i]]) ++Ans;
    	printf("%d
    ",Ans);
    	for (rr int i=1;i<=n;++i)
    	    if (v[col[i]]&&ans==dp[col[i]])
    		    printf("%d ",i);
    	return 0;
    } 
    
  • 相关阅读:
    Flume配置
    HDU5312 Sequence
    CF(D. Fibonacci Sums)dp计数
    【算法拾遗】二分查找递归非递归实现
    ubuntu下怎么给普通用户赋予sudo权限
    在Oracle 11.2.0.1.0下dbms_stats.gather_table_stats收集直方图不准
    ZOJ3622 Magic Number(水题)
    小试ImageMagik——开发篇
    一起talk C栗子吧(第二十七回:C语言实例--插入排序)
    依据输入的内容打印出菱形
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13928646.html
Copyright © 2011-2022 走看看