• CodeForces 1361E James and the Chase


    CodeForces 1361E James and the Chase

    https://codeforces.com/contest/1361/problem/E

    Uthgcd.png

    Tutorial

    https://codeforces.com/blog/entry/78355

    考虑对于一个点如何判断它是否为interesting的.

    以它为根建立dfs树,发现它为interesting的条件就是dfs树上没有横叉边.

    由于20%的限制,我们可以随机(T=100)次,这样就可以找到某个interesting的点(r),或判断其小于20%.

    (r)为根建立dfs树,现在树上只有返祖边和树边.考虑怎样的点是interesting的.

    考虑树上不是(r)的某个点(u),那么发现条件为(u)到它的所有祖先都只有一条简单路径,那么如果(u)子树中有大于1个连向(u)的祖先的边,那么(u)一定不合法.由于这是一个强连通分量,所以至少也存在一条边,设其连向(v),那么根据刚才的条件,可以递归的发现,(u)合法的条件就是(v)合法.

    复杂度(O(Tn))

    Code

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <vector>
    #define debug(...) fprintf(stderr,__VA_ARGS__)
    using namespace std;
    inline char gc() {
    //	return getchar();
    	static char buf[100000],*l=buf,*r=buf;
    	return l==r&&(r=(l=buf)+fread(buf,1,100000,stdin),l==r)?EOF:*l++; 
    }
    template<class T> void rd(T &x) {
    	x=0; int f=1,ch=gc();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    	while(ch>='0'&&ch<='9'){x=x*10-'0'+ch;ch=gc();}
    	x*=f;
    }
    typedef unsigned long long ull;
    const int inf=1e9;
    const int maxn=1e5+50;
    int t,n,m;
    int head[maxn];
    int dep[maxn],tag[maxn],mn[maxn];
    bool mark[maxn],vis[maxn];
    bool good[maxn];
    struct edge {
    	int to,nex;
    	edge(int to=0,int nex=0):to(to),nex(nex){}
    };
    vector<edge> G;
    inline void addedge(int u,int v) {
    	G.push_back(edge(v,head[u])),head[u]=G.size()-1;
    }
    inline ull Rand() {
    	static ull seed=0;
    	seed^=rand();
    	seed^=seed<<13;
    	seed^=seed>>17;
    	seed^=seed<<5;
    	return seed;
    }
    bool dfs0(int u) {
    	vis[u]=mark[u]=1;
    	for(int i=head[u];~i;i=G[i].nex) {
    		int v=G[i].to;
    		if(!vis[v]) {
    			if(!dfs0(v)) return 0;
    		}
    		else {
    			if(!mark[v]) return 0;
    		}
    	}
    	mark[u]=0;
    	return 1;
    }
    void dfs1(int u) {
    	vis[u]=1;
    	mn[u]=u;
    	for(int i=head[u];~i;i=G[i].nex) {
    		int v=G[i].to;
    		if(!vis[v]) {
    			dep[v]=dep[u]+1;
    			dfs1(v);
    			tag[u]+=tag[v];
    			if(dep[mn[v]]<dep[mn[u]]) mn[u]=mn[v];
    		}
    		else {
    			++tag[u],--tag[v];
    			if(dep[v]<dep[mn[u]]) mn[u]=v;
    		}
    	}
    	if(tag[u]<=1) good[u]=1;
    }
    void dfs2(int u) {
    	vis[u]=1;
    	if(mn[u]!=n+1) good[u]&=good[mn[u]];
    	for(int i=head[u];~i;i=G[i].nex) {
    		int v=G[i].to;
    		if(!vis[v]) dfs2(v);
    	}
    }
    bool check(int x) {
    	for(int i=1;i<=n;++i) mark[i]=vis[i]=0;
    	return dfs0(x);
    }
    void sol(int r) {
    	for(int i=1;i<=n;++i) vis[i]=0; 
    	dep[r]=0,dfs1(r);
    	for(int i=1;i<=n;++i) vis[i]=0;
    	dfs2(r);
    }
    void clear() {
    	G.clear();
    	for(int i=1;i<=n;++i) {
    		head[i]=-1;
    		good[i]=tag[i]=0;
    	}
    }
    int main() {
    	srand((ull)(new char));
    	rd(t);
    	memset(head,-1,sizeof(head));
    	for(int kase=1;kase<=t;++kase) {
    		clear();
    		rd(n),rd(m);
    		for(int i=1;i<=m;++i) {
    			int u,v; rd(u),rd(v);
    			addedge(u,v);
    		}
    		int T=100,r=-1; while(T--) {
    			r=Rand()%n+1;
    			if(check(r)) break;
    			r=-1;
    		}
     		if(r==-1) {puts("-1"); continue;}
    		sol(r);
    		vector<int> an;
    		for(int i=1;i<=n;++i) if(good[i]) an.push_back(i);
    		if(an.size()*5<n) puts("-1");
    		else  {
    			for(int i=0;i<an.size();++i) {
    				if(i) printf(" ");
    				printf("%d",an[i]);
    			}
    			printf("
    ");
    		}
    	}
    	return 0;
    } 
    
  • 相关阅读:
    深入浅出Java三大框架SSH与MVC的设计模式
    excel 日期/数字格式不生效需要但双击才会生效的解决办法
    如何隐藏DIV对象
    使用 Arrays 类操作 Java 中的数组
    Java常量的应用
    Windows操作系统下tomcat安装版图文教程
    命名sql数据集
    【转载】如何写一个框架:步骤(下)
    【转载】如何写一个框架:步骤(上)
    C++Builder实现二分查找法
  • 原文地址:https://www.cnblogs.com/ljzalc1022/p/13297368.html
Copyright © 2020-2023  润新知