Educational Codeforces Round 46 (Rated for Div. 2) E.We Need More Bosses(双连通分量+缩点)

题目链接

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

题意

给出一张图,设两点s,t,则可在s,t两点间的必经之边(去掉这条边,s、t不可达)上放置怪物,找到s、t,使得它可放置最多的怪物。输出可放置的最多的怪物。

题解

利用tarjan求出该图的所有边-双连通分量,缩点,形成一棵树,求出树的直径,得到答案。

代码

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=3e5+10;
void read(int &x){
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
struct Edge
{
    int no,v,next;     
}edges[2*maxn];

int n,m,ebcnum;         //节点数目,无向边的数目,边_双连通分量的数目
int e,head[maxn];
int pre[maxn];          //第一次访问的时间戳
int dfs_clock;          //时间戳
int isbridge[maxn*2],cl[maxn];     //标记边是否为桥
vector<int> ebc[maxn];  //边_双连通分量
vector<int>mp[maxn];
set<int>ss[maxn];
void addedges(int num,int u,int v)    //加边
{
    edges[e].no = num;
    edges[e].v = v;
    edges[e].next = head[u];
    head[u] = e++;
    edges[e].no = num++;
    edges[e].v = u;
    edges[e].next = head[v];
    head[v] = e++;
}

int dfs_findbridge(int u,int fa)    //找出所有的桥
{
    int lowu = pre[u] = ++dfs_clock;
    for(int i=head[u];i!=-1;i=edges[i].next)
    {
        int v = edges[i].v;
        if(!pre[v])
        {
            int lowv = dfs_findbridge(v,u);
            lowu = min(lowu,lowv);
            if(lowv > pre[u])
            {
                isbridge[edges[i].no] = 1; //桥
            }
        }
        else if(pre[v] < pre[u] && v != fa)
        {
            lowu = min(lowu,pre[v]);
        }
    }
    return lowu;
}

void dfs_coutbridge(int u,int fa){
    ebc[ebcnum].push_back(u);
    pre[u] = ++dfs_clock;
    for(int i=head[u];i!=-1;i=edges[i].next)
    {
        int v = edges[i].v;
        if(!isbridge[edges[i].no] && !pre[v]) dfs_coutbridge(v,u);
    }
}

void init()
{
    memset(pre,0,sizeof(pre));
    memset(isbridge,0,sizeof(isbridge));
    memset(head,-1,sizeof(head));
    e = 0; ebcnum = 1;
}

int dep[maxn],vis[maxn],ans=0;
//vector<int>tem;
void dfs(int u){
	int i,l1=0,l2=0,f=0;
	for(i=0;i<mp[u].size();i++){
		int v=mp[u][i];
		if(!vis[v]){
			f=1;
			vis[v]=1;
			dfs(v);
			if(l1==0){
				l1=dep[v]+1;
			}
			else if(dep[v]+1>l1){
				l2=l1;
				l1=dep[v]+1;
			}
			else if(dep[v]+1>l2){
				l2=dep[v]+1;
			}
		}
	}
	if(!f){
		dep[u]=0;return;
	}
	ans=max(ans,l1+l2);
	dep[u]=l1;	
}


int ui[maxn],vi[maxn];
int main(){
	int i,j;
	read(n);read(m);
	init();
	for(i=0;i<m;i++){
		read(ui[i]);read(vi[i]);
		addedges(i,ui[i],vi[i]);
	}
	dfs_findbridge(1,-1);
	memset(pre,0,sizeof(pre));
    for(i=1;i<=n;i++){
        if(!pre[i]){
            ebc[ebcnum].clear();
            dfs_coutbridge(i,-1);
            ebcnum++;
        }
    }
    ebcnum--;
    for(i=1;i<=ebcnum;i++){
    	for(j=0;j<ebc[i].size();j++){
    		int u=ebc[i][j];
    		cl[u]=i;
		}
	}
    for(i=0;i<m;i++){
    	int x=cl[ui[i]],y=cl[vi[i]];
		if(!ss[x].count(y)){
			ss[x].insert(y);
			mp[x].push_back(y);
		}
		if(!ss[y].count(x)){
			ss[y].insert(x);
			mp[y].push_back(x);
		}
	}
    memset(vis,0,sizeof(vis));
    memset(dep,0,sizeof(dep));
	vis[1]=1;
	dfs(1);
	cout<<ans;
	return 0;
}
发布了27 篇原创文章 · 获赞 11 · 访问量 3579

猜你喜欢

转载自blog.csdn.net/Megurine_Luka_/article/details/103019862