题目链接:http://codeforces.com/contest/1000/problem/E
直接点双跑出来,然后图就变成了一棵树,然后跑树的直径,就是答案,题目描述挺迷的。。。
代码:
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int MAXN=3e5+5;//点数
const int MAXM=6e5+5;//边数,因为是无向图,所以这个值要*2
struct Edge
{
int to,next;
bool cut;//是否是桥标记
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];//Belong数组的值是1~block
int Index,top;
int block;//边双连通块数
bool Instack[MAXN];
void addedge(int u,int v)
{
edge[tot].to=v;edge[tot].next=head[u];edge[tot].cut=false;
head[u]=tot++;
}
void Tarjan(int u,int pre)
{
int v;
bool flag=false;
Low[u]=DFN[u]=++Index;
Stack[top++]=u;
Instack[u]=true;
for(int i=head[u];~i;i=edge[i].next)
{
v=edge[i].to;
if(v==pre&&(!flag))//或者标记边的id
{
flag=true;
continue;
}
if(!DFN[v])
{
Tarjan(v,u);
if(Low[u]>Low[v]) Low[u]=Low[v];
if(Low[v]>DFN[u])
{
edge[i].cut=true;
edge[i^1].cut=true;
}
}
else if(Instack[v]&&Low[u]>DFN[v])
Low[u]=DFN[v];
}
if(Low[u]==DFN[u])
{
block++;
do
{
v=Stack[--top];
Instack[v]=false;
Belong[v]=block;
}
while(v!=u);
}
}
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
void solve()
{
memset(DFN,0,sizeof(DFN));
memset(Instack,false,sizeof(Instack));
memset(Belong,0,sizeof(Belong));
Index=top=block=0;
Tarjan(1,0);
}
vector<int> E[MAXN];
int mx,root;
void dfs(int now,int f,int dp)
{
if(dp>mx)
{
root=now;
mx=dp;
}
for(auto v:E[now])
{
if(v==f) continue;
dfs(v,now,dp+1);
}
}
int main()
{
int n,m;
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
solve();
for(int i=1;i<=n;i++)
{
for(int j=head[i];~j;j=edge[j].next)
{
if(edge[j].cut)
{
int v=edge[j].to;
E[Belong[i]].pb(Belong[v]);
}
}
}
root=0;mx=0;
dfs(1,0,0);
mx=0;
dfs(root,0,0);
printf("%d\n",mx);
}