牛客练习赛56 E 小雀和他的王国

点点圈 提交于 2020-02-13 01:55:42

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

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!