题目链接:https://ac.nowcoder.com/acm/contest/3566/E
思路:tarjan缩点,桥重建图,dfs跑树的直径。
1 #include <iostream>
2 #include <cstdio>
3 #include <vector>
4 #include <algorithm>
5 using namespace std;
6 typedef long long ll;
7
8 const int N = (int)2e5+100,mod = (int)1e9+7;
9 struct node{
10 int to,nxt;
11 }e[N<<1];
12 vector<pair<int,int> > cut;
13 int n,m,u,v,tot,tim,top,scc_num,bridge;
14 int head[N],dfn[N],low[N],s[N],scc_no[N],d[N];
15 bool vis[N];
16
17 ll quick(ll a,ll b){
18 ll ans=1;
19 a=a%mod;
20 while(b!=0){
21 if(b&1) ans=(ans*a)%mod;
22 b>>=1;
23 a=(a*a)%mod;
24 }
25 return ans;
26 }
27
28 inline void add(int u,int v){
29 e[tot].to = v; e[tot].nxt = head[u]; head[u] = tot++;
30 e[tot].to = u; e[tot].nxt = head[v]; head[v] = tot++;
31 }
32
33 void tarjan(int now,int pre){
34 dfn[now] = low[now] = ++tim;
35 s[top++] = now;
36 int pre_cnt = 0;
37 for(int o = head[now]; ~o; o = e[o].nxt){
38 int to = e[o].to;
39 if(to == pre && pre_cnt == 0){ pre_cnt = 1; continue; }
40 if(!dfn[to]){
41 tarjan(to,now);
42 low[now] = min(low[now],low[to]);
43 if(dfn[now] < low[to]) cut.push_back(make_pair(now,to));
44 }else low[now] = min(low[now],dfn[to]);
45 }
46
47 if(dfn[now] == low[now]){
48 ++scc_num;
49 int tmp;
50 do{
51 tmp = s[--top];
52 scc_no[tmp] = scc_num;
53 }while(now != tmp);
54 }
55 }
56
57 void dfs(int now,int pre){
58 vis[now] = 1;
59 d[now] = d[pre]+1;
60 for(int o = head[now]; ~o; o = e[o].nxt){
61 int to = e[o].to;
62 if(vis[to]) continue;
63 dfs(to,now);
64 }
65 }
66
67 void rebuild(){
68 for(int i = 0; i <= scc_num; ++i) head[i] = -1; tot = 0;
69 bridge = cut.size();
70 for(int i = 0; i < bridge; ++i){
71 // printf("%d %d\n",scc_no[cut[i].first],scc_no[cut[i].second]);
72 add(scc_no[cut[i].first],scc_no[cut[i].second]);
73 }
74 /*
75 for(int i = 1; i <= scc_num; ++i){
76 printf("u = %d\t",i);
77 for(int o = head[i]; ~o; o = e[o].nxt) printf("%d ",e[o].to);
78 cout << endl;
79 }*/
80 }
81
82
83 void show_info(){
84 for(int i = 1; i <= n; ++i){
85 printf("loc = %d scc_no = %d\n",i,scc_no[i]);
86 }
87 }
88
89 void solve(){
90
91 for(int i = 1; i <= n; ++i) head[i] = -1; tot = 0;
92 for(int i = 1; i <= m; ++i){
93 scanf("%d%d",&u,&v);
94 add(u,v);
95 }
96 tarjan(1,0);
97 rebuild();
98 int s = 1;
99 for(int i = 0; i <= scc_num; ++i){
100 d[i] = -1; vis[i] = 0;
101 }
102 dfs(s,0);
103 for(int i = 0; i <= scc_num; ++i){
104 if(d[s] < d[i]) s = i;
105 }
106 for(int i = 0; i <= scc_num; ++i){
107 d[i] = -1; vis[i] = 0;
108 }
109 dfs(s,0);
110 int max_len = 0;
111 for(int i = 0; i <= scc_num; ++i) max_len = max(max_len,d[i]);
112 // printf("max_len = %d\n",max_len);
113 //printf("%lf\n",(double)(bridge-max_len)/(m+1));
114 printf("%lld\n",1ll*(bridge-max_len)*quick(m+1,mod-2)%mod);
115 }
116
117 int main(){
118
119 scanf("%d%d",&n,&m);
120 solve();
121 //show_info();
122
123
124 return 0;
125 }
来源:https://www.cnblogs.com/SSummerZzz/p/12302013.html