zoukankan      html  css  js  c++  java
  • 题解 P5058 [ZJOI2004]嗅探器

    一道 (tarjan)

    蓝军共有两个信息中心,红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心互相交换的所有信息。

    也就是说,(a)(b) 的所有路径必须经过 那个中间服务器。

    -----> 如果删去那个中间服务器,(a)(b) 不联通。

    -----> 那个中间服务器是一个割点。(一个特殊的割点)

    假设用 (now) 表示当前结点, (v) 表示儿子。

    (exa[now]) 表示当前结点所在子树中有无 (a)

    (exb[now]) 同理

    那么当且仅当以下条件全部发生时,(now) 可以更新 (ans)

    • now为割点(这是显然的,上面已分析)
    • 在以上条件成立时,(a)(b) 只能有一个在 (v) 的子树内(因为删去 (now)(v) 的子树的点与其他点不联通)(如果a,b都不在v内,now也可能是答案,但这是通过其他子树来实现的)。
    • now!=a&&now!=b(一定不要忘记)(看清题目)

    Code

    #include<cstdio>
    #include<iostream>
    #define LL long long
    #define rint register int
    using namespace std;
    namespace FastIO
    {
    char c;
    bool sign;
    template<class T>
    inline void read(T &x)
    {
    	x=0;
    	sign=false;
    	for(c=getchar();c<'0'||c>'9';c=getchar()) 
    		if(c=='-') 
    			sign=true;
    	for(;c>='0'&&c<='9';c=getchar()) 
    		x=(x<<1)+(x<<3)+(c&15);
    	if(sign) x=~x+1;
    	return;
    }
    }
    using FastIO::read;
    //======================================
    const int N=2e5+5;
    const int M=1e6+5;
    int one[N];
    int ver[M],Next[M];
    int tot=0;
    inline void AddEdge(const int &a,const int &b)
    {
    	tot++;
    	Next[tot]=one[a];
    	one[a]=tot;
    	ver[tot]=b;
    	return;
    }
    //======================================
    int n;
    int a,b;
    int dfn[N],low[N],times=0;
    bool exa[N],exb[N]; // 在搜索树的子树中有没有 a,b
    int ans=N+3;
    void tarjan(int now,const int &fa)
    {
    	dfn[now]=low[now]=++times;
    	rint i,v,child=0;
    	for(i=one[now];i>0;i=Next[i]) {
    		v=ver[i];
    		if(!dfn[v]) {
    			child++;
    			tarjan(v,now);
    			low[now]=min(low[now],low[v]);
    			if(exa[v]) exa[now]=true;
    			if(exb[v]) exb[now]=true; 
    			if((fa==-1&&child>1)||(fa!=-1&&low[v]>=dfn[now]))
    				if(exa[v]^exb[v]&&now!=a&&now!=b) // !!!
    					ans=min(ans,now);
    		}
    		else if(v!=fa) 
    			low[now]=min(low[now],dfn[v]);
    	}
    	return;
    } 
    int main()
    {
    //	freopen("1.in","r",stdin);
    	rint i;
    	int x,y;
    	read(n);
    	while(true) {
    		read(x); read(y);
    		if(x==0&&y==0) 
    			break;
    		AddEdge(x,y);
    		AddEdge(y,x);
    	}
    	read(a); read(b);
    	exa[a]=true;
    	exb[b]=true;
    //	tarjan(a,-1);
    	for(i=1;i<=n;i++) 
    		if(dfn[i]==0) 
    			tarjan(i,-1);
    	if(ans==N+3) 
    		puts("No solution");
    	else printf("%d
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    Mysql根据字段汉字首字母排序
    Springboot学习—CommandLineRunner接口(转载)
    JavaWeb—Nginx介绍(转载)
    linux下后台启动springboot项目(转载)
    Springboot入门5-项目打包部署(转载)
    Linux学习—redis安装配置及远程连接
    Linux学习—maven安装
    Linux学习—mysql安装配置及远程连接
    Linux学习—yum命令(转载)
    Linux学习—rpm包管理
  • 原文地址:https://www.cnblogs.com/cjl-world/p/13168492.html
Copyright © 2011-2022 走看看