题目链接:https://ac.nowcoder.com/acm/contest/3566/E
思路:tarjan缩点,桥重建图,dfs跑树的直径。
1 #include2 #include 3 #include 4 #include 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 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 }