2022 Niu Ke dritte Runde für mehrere Schulen

F. Lehen

Abschlussfrage:

Zuerst muss das ganze Bild verbunden werden

Suchen Sie den Schnittpunkt für das Originalbild und klicken Sie auf den doppelten Schrumpfpunkt

Wenn es keinen Schnittpunkt gibt, bedeutet dies JA

Erstellen Sie ein neues Diagramm, um den Grad jedes Punktpaars zu zählen

JA, wenn und nur wenn der Graph nach dem Schrumpfen von Punkten eine Kette ist und sowohl u als auch v im Punktpaar mit dem ersten und letzten Grad 1 sind

NEIN NEIN

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");
	}
}

Guess you like

Origin blog.csdn.net/m0_51780913/article/details/125984201