题目链接
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;
}