• bzoj 3887: Grass Cownoisseur Tarjan+Topusort


    题目:

    给一个有向图,然后选一条路径起点终点都为1的路径出来,有一次机会可以沿某条边逆方向走,问最多有多少个点可以被经过?(一个点在路径中无论出现多少正整数次对答案的贡献均为1)

    题解:

    首先考虑简单一些的问题
    如果没有逆向的机会,那么(ans)即为(1)所在的强连通分量的大小。
    但是现在有一个逆向的机会
    如果我们将缩点后的(DAG)搞出来的话就可以发现:
    一定是从(1)的连通块出发走到别的地方然后通过走逆向边返回一个可以到达(1)的路径上。
    那么我们可以预处理每个点到根的最大(siz)之和根到每个点的路上的最大(siz)之和。
    然后枚举每条边进行(O(1))判断即可.

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    inline void read(int &x){
        x=0;char ch;bool flag = false;
        while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
        while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    #define rg register int
    #define rep(i,a,b) for(rg i=(a);i<=(b);++i)
    #define per(i,a,b) for(rg i=(a);i>=(b);--i)
    const int maxn = 100010;
    struct Edge{
        int to,next;
    }G[maxn];
    int head[maxn],cnt;
    void add(int u,int v){
        G[++cnt].to = v;
        G[cnt].next = head[u];
        head[u] = cnt;
    }
    int dfn[maxn],low[maxn],dfs_clock;
    int sta[maxn],top,belong[maxn];
    int scc_cnt,siz[maxn];
    #define v G[i].to
    void dfs(int u){
        dfn[u] = low[u] = ++ dfs_clock;
        sta[++top] = u;
        for(rg i = head[u];i;i=G[i].next){
    		if(!dfn[v]){
    		    dfs(v);
    		    low[u] = min(low[u],low[v]);
    		}else if(!belong[v]) low[u] = min(low[u],dfn[v]);
        }
        if(dfn[u] == low[u]){
    		++ scc_cnt;
    		while(1){
    		    int x = sta[top--];
    		    belong[x] = scc_cnt;
    		    siz[scc_cnt] ++ ;
    		    if(x == u) break;
    		}
        }
    }
    #undef v
    struct Topu{
        struct Edge{
    		int to,next;
        }G[maxn];
        int head[maxn],cnt,deg[maxn];
        void add(int u,int v){
    		G[++cnt].to = v;
    		G[cnt].next = head[u];
    		head[u] = cnt;
    		++ deg[v];
        }
    #define v G[i].to
        int q[maxn],l,r,f[maxn];
        void bfs(){
    		memset(f,-0x3f,sizeof f);
    		f[belong[1]] = siz[belong[1]];l = 0;r = -1;
    		rep(i,1,scc_cnt){
    		    if(deg[i] == 0) q[++r] = i;
    		}
    		while(l <= r){
    		    int u = q[l++];
    		    for(rg i = head[u];i;i=G[i].next){
    				f[v] = max(f[v],f[u] + siz[v]);
    				if(-- deg[v] == 0) q[++r] = v;
    		    }
    		}return ;
        }
    #undef v
    }a,b;
    struct Node{
        int u,v;
    }e[maxn];
    int main(){
        int n,m;read(n);read(m);
        int u,v;
        rep(i,1,m){
    		read(u);read(v);
    		e[i].u = u;e[i].v = v;
    		add(u,v);
        }
        rep(i,1,n) if(!dfn[i]) dfs(i);
        rep(i,1,m){
    		if(belong[e[i].u] == belong[e[i].v]) continue;
    		a.add(belong[e[i].u],belong[e[i].v]);
    		b.add(belong[e[i].v],belong[e[i].u]);
        }a.bfs();b.bfs();
        int ans = siz[belong[1]] << 1;
        rep(i,1,m){
    		if(belong[e[i].u] == belong[e[i].v]) continue;
    		ans = max(ans,a.f[belong[e[i].v]] + b.f[belong[e[i].u]]);
        }
        printf("%d
    ",ans - siz[belong[1]]);
        return 0;
    }
    
    
  • 相关阅读:
    JavaWeb WebBrowserTool KernelEngine
    类模板 C++快速入门45
    动态数组的使用
    动态数组的使用
    鱼C小甲鱼
    栈原理演示
    鱼C小甲鱼
    类模板 C++快速入门45
    delphi实例
    栈原理演示
  • 原文地址:https://www.cnblogs.com/Skyminer/p/7001379.html
Copyright © 2020-2023  润新知