2022牛客多校第三场

F.Fief

结论题:

首先整张图需要是联通的

对原图找割点,点双缩点

若不存在割点,意味着都是YES

建立新图统计每一个点双的度数

当且仅当缩点后的图为一条链且u和v都在首尾度数为1的点双中才是YES

否则NO

const int N = 200010, M = 400010;
int n, m, k, timestamp, top, idx, dcc_cnt, ans, root,id[N];
int e[M], ne[M], h[N], stk[M], dfn[N], low[N], deg[N],d[M],from[N];
bool ins[M], is_bridge[M],cut[N];
vector<int> dcc[N];

void add(int a,int b){
    
    
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

void tarjan(int u){
    
    
    dfn[u] = low[u] = ++timestamp;
    stk[++ top] = u;
    
    if(u == root && h[u] == -1){
    
     //孤立点
        dcc_cnt ++;
        dcc[dcc_cnt].push_back(u);
        return ;
    }
    
    int cnt = 0;
    for(int i=h[u];~i;i=ne[i]){
    
    
        int j = e[i];
        if(!dfn[j]){
    
    
            tarjan(j);
            low[u] = min(low[u], low[j]);
            
            if(dfn[u] <= low[j]) {
    
    
                cnt++;
                if(u!=root || cnt > 1)  cut[u] = true;
                dcc_cnt ++;
                int y;
                do{
    
    
                	y = stk[top --];
                    id[y] = dcc_cnt;
                    dcc[dcc_cnt].push_back(y);
                }while(y!=j);
                dcc[dcc_cnt].push_back(u);
            }
        }
        else low[u] = min(low[u], dfn[j]);
    }
}

vector<int> edge[N];
int fa[N];
int find(int x){
    
    
	return fa[x]==x?fa[x]:fa[x]=find(fa[x]);
}

void solve(){
    
    
	n=read(),m=read();
	rep(i,1,n) fa[i]=i;
	rep(i,1,m){
    
    
		int u=read(),v=read();
		add(u, v), add(v, u);
		int pu=find(u),pv=find(v);
		if(pu!=pv) fa[pu]=pv;
	}
	for(root=1;root<=n;++root)
		if(!dfn[root])
			tarjan(root);
	
	int tmp=0;
	bool connec = true;
	for(int i=1;i<=n;++i)
		if(find(i)==i) tmp ++;
	if(tmp>1) connec=false;
	bool NO = 0, YES = 1;
	for(int i=1;i<=n;++i)
		if(cut[i]) {
    
    YES=0; break;}

	int num=dcc_cnt;
	for(int i=1;i<=dcc_cnt;++i) {
    
    
		for(auto u:dcc[i]){
    
    
			if(cut[u]) {
    
    
				if(!from[u]) from[u]=++num;
				edge[from[u]].push_back(i);
				edge[i].push_back(from[u]);
				d[i] ++; 
				d[from[u]] ++;
				if(d[i]>=3||d[from[u]]>=3) NO = 1;
			}
			else from[u]=i;
		}
	}
	int q=read();
	while(q--){
    
    
		int u=read(),v=read();
		if(!connec||NO) puts("NO");
		else if(YES) puts("YES");
		else if(d[from[u]]==1&&d[from[v]]==1&&from[u]!=from[v]) puts("YES");
		else puts("NO");
	}
}

猜你喜欢

转载自blog.csdn.net/m0_51780913/article/details/125984201