转载请注明出处:http://tokitsukaze.live/

题目链接:http://codeforces.com/problemset/problem/1000/E


题意:一条路径上必经的边为关键边,现在让你找一条路径,使得其关键边最多,输出最多的数量。


题解:
如果一条路径上面有环,那么这个环的任意一条边都不是关键边。所以先缩点,缩点完变成一棵树,那么在一棵树上找最多的关键边,显然就是求直径。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include <bits/stdc++.h>
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define mem(a,b) memset((a),(b),sizeof(a))
#define MP make_pair
#define pb push_back
#define fi first
#define se second
#define sz(x) (int)x.size()
#define all(x) x.begin(),x.end()
using namespace std;
#define _GLIBCXX_PERMIT_BACKWARD_HASH
#include <ext/hash_map>
using namespace __gnu_cxx;
struct str_hash{size_t operator()(const string& str)const{return __stl_hash_string(str.c_str());}};
typedef long long ll;
typedef unsigned long long ull;
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define PDD pair<double,double>
#define VI vector<int>
#define VL vector<ll>
const int INF=0x3f3f3f3f;
const ll LLINF=0x3f3f3f3f3f3f3f3f;
const double PI=acos(-1.0);
const double eps=1e-4;
const int MAX=3e5+10;
const ll mod=1e9+7;
namespace Tarjan
{
int bcc,top,tot,n;
vector<int> mp[MAX];
int low[MAX],dfn[MAX],belong[MAX],fa[MAX];
int stk[MAX];
void dfs(int x,int pre)
{
int to,i,temp,k;
stk[top++]=x;
low[x]=dfn[x]=++tot;
fa[x]=pre;
k=0;
for(auto to:mp[x])
{
if(to==pre&&!k)
{
k++;
continue;
}
if(!dfn[to])
{
dfs(to,x);
low[x]=min(low[x],low[to]);
}
else low[x]=min(low[x],dfn[to]);
}
if(low[x]==dfn[x])
{
bcc++;
do
{
temp=stk[--top];
belong[temp]=bcc;
}while(temp!=x);
}
}
void work(int _n,vector<int> e[])
{
n=_n;
for(int i=1;i<=n;i++)
{
mp[i]=e[i];
low[i]=dfn[i]=fa[i]=stk[i]=0;
}
bcc=top=tot=0;
for(int i=1;i<=n;i++)
{
if(!dfn[i]) dfs(i,i);
}
}
void rebuild(vector<int> e[])
{
int i,t;
for(i=1;i<=n;i++) e[i].clear();
for(i=1;i<=n;i++)
{
t=fa[i];
if(belong[i]!=belong[t])
{
e[belong[i]].pb(belong[t]);
e[belong[t]].pb(belong[i]);
}
}
}
}
int Tree_Diameter(const vector<int> e[])
{
static int h[MAX];
int mx,rt;
function<void(int,int)> dfs=[&](int x,int fa)
{
h[x]=h[fa]+1;
for(auto to:e[x])
{
if(to==fa) continue;
dfs(to,x);
}
if(h[x]>mx)
{
mx=h[x];
rt=x;
}
};
mx=rt=-1;
dfs(1,0);
dfs(rt,0);
return mx;
}
vector<int> mp[MAX],res[MAX];
int main()
{
int n,m,a,b,i;
while(~scanf("%d%d",&n,&m))
{
for(i=1;i<=n;i++) mp[i].clear();
while(m--)
{
scanf("%d%d",&a,&b);
mp[a].pb(b);
mp[b].pb(a);
}
Tarjan::work(n,mp);
Tarjan::rebuild(res);
printf("%d\n",Tree_Diameter(res)-1);
}
return 0;
}