fork download
  1. #include <bits/stdc++.h>
  2. #define ll long long
  3. #define INF 1000000005
  4. #define MOD 1000000007
  5. #define EPS 1e-10
  6. #define rep(i,n) for(int i=0;i<(int)(n);++i)
  7. #define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)
  8. #define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)
  9. #define each(a,b) for(auto& (a): (b))
  10. #define all(v) (v).begin(),(v).end()
  11. #define len(v) (int)(v).size()
  12. #define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())
  13. #define cmx(x,y) x=max(x,y)
  14. #define cmn(x,y) x=min(x,y)
  15. #define fi first
  16. #define se second
  17. #define pb push_back
  18. #define show(x) cout<<#x<<" = "<<(x)<<endl
  19. #define sar(a,n) {cout<<#a<<":";rep(pachico,n)cout<<" "<<a[pachico];cout<<endl;}
  20.  
  21. using namespace std;
  22.  
  23. template<typename S,typename T>auto&operator<<(ostream&o,pair<S,T>p){return o<<"{"<<p.fi<<","<<p.se<<"}";}
  24. template<typename T>auto&operator<<(ostream&o,set<T>s){for(auto&e:s)o<<e<<" ";return o;}
  25. template<typename S,typename T,typename U>
  26. auto&operator<<(ostream&o,priority_queue<S,T,U>q){while(!q.empty())o<<q.top()<<" ",q.pop();return o;}
  27. template<typename K,typename T>auto&operator<<(ostream&o,map<K,T>&m){for(auto&e:m)o<<e<<" ";return o;}
  28. template<typename T>auto&operator<<(ostream&o,vector<T>v){for(auto&e:v)o<<e<<" ";return o;}
  29. void ashow(){cout<<endl;}template<typename T,typename...A>void ashow(T t,A...a){cout<<t<<" ";ashow(a...);}
  30. template<typename S,typename T,typename U>
  31. struct TRI{S fi;T se;U th;TRI(){}TRI(S f,T s,U t):fi(f),se(s),th(t){}
  32. bool operator<(const TRI&_)const{return(fi==_.fi)?((se==_.se)?(th<_.th):(se<_.se)):(fi<_.fi);}};
  33. template<typename S,typename T,typename U>
  34. auto&operator<<(ostream&o,TRI<S,T,U>&t){return o<<"{"<<t.fi<<","<<t.se<<","<<t.th<<"}";}
  35.  
  36. typedef pair<int, int> P;
  37. typedef pair<ll, ll> pll;
  38. typedef TRI<int, int, int> tri;
  39. typedef vector<int> vi;
  40. typedef vector<ll> vl;
  41. typedef vector<vi> vvi;
  42. typedef vector<vl> vvl;
  43. typedef vector<P> vp;
  44. typedef vector<double> vd;
  45. typedef vector<string> vs;
  46.  
  47. const int MAX_N = 100005;
  48.  
  49. class FindingAllCycles {
  50. private:
  51. struct node {
  52. int prev, next, to;
  53. node(const int _prev, const int _next, const int _to)
  54. : prev(_prev), next(_next), to(_to){}
  55. };
  56. const int V;
  57. vector<vector<node> > G;
  58. vector<stack<int> > block_stack;
  59. stack<int> st;
  60. bool *fix, *blocked, *used;
  61. bool enumerate;
  62. void erase_edge(const int u, const int id){
  63. G[u][G[u][id].next].prev = G[u][id].prev;
  64. G[u][G[u][id].prev].next = G[u][id].next;
  65. }
  66. void scc_dfs(const int u, int& tm, int& cnt,
  67. vector<int>& ord, vector<int>& low, vector<int>& cmp, stack<int>& st){
  68. ord[u] = low[u] = tm++, st.push(u);
  69. for(int id = G[u][0].next; id != 0; id = G[u][id].next){
  70. const int v = G[u][id].to;
  71. if(ord[v] < 0){
  72. scc_dfs(v, tm, cnt, ord, low, cmp, st);
  73. low[u] = min(low[u], low[v]);
  74. }else if(cmp[v] < 0){
  75. low[u] = min(low[u], ord[v]);
  76. }
  77. if(cmp[v] >= 0) erase_edge(u, id);
  78. }
  79. if(ord[u] == low[u]){
  80. while(true){
  81. const int v = st.top();
  82. st.pop(), cmp[v] = cnt;
  83. if(v == u) break;
  84. }
  85. ++cnt;
  86. }
  87. }
  88. void scc(){
  89. vector<int> ord(V, -1), low(V), cmp(V, -1);
  90. stack<int> st;
  91. int tm = 0, cnt = 0;
  92. for(int i = 0; i < V; ++i){
  93. if(ord[i] < 0) scc_dfs(i, tm, cnt, ord, low, cmp, st);
  94. }
  95. }
  96. void unblock(const int u){
  97. blocked[u] = false;
  98. while(!block_stack[u].empty()){
  99. const int v = block_stack[u].top();
  100. block_stack[u].pop();
  101. if(blocked[v]) unblock(v);
  102. }
  103. }
  104. bool dfs(const int u, const int s, vector<int>& path, vector<int>& ver_list){
  105. bool flag = false;
  106. path.push_back(u);
  107. blocked[u] = true;
  108. if(!used[u]) used[u] = true, ver_list.push_back(u);
  109. for(int id = G[u][0].next; id != 0; id = G[u][id].next){
  110. const int v = G[u][id].to;
  111. if(fix[v]){
  112. erase_edge(u, id);
  113. continue;
  114. }
  115. if(v == s){
  116. if(enumerate) ans.push_back(path);
  117. ++count, flag = true;
  118. }else if(!blocked[v]){
  119. if(dfs(v, s, path, ver_list)) flag = true;
  120. }
  121. }
  122. if(flag) unblock(u);
  123. else{
  124. for(int id = G[u][0].next; id != 0; id = G[u][id].next){
  125. block_stack[G[u][id].to].push(u);
  126. }
  127. }
  128. path.pop_back();
  129. return flag;
  130. }
  131.  
  132. public:
  133. vector<vector<int> > ans;
  134. int count;
  135. FindingAllCycles(const int node_size)
  136. : V(node_size), G(V, vector<node>{{0, 0, -1}}), block_stack(V),
  137. fix(new bool[V]()), blocked(new bool[V]()), used(new bool[V]()), count(0){}
  138. ~FindingAllCycles(){
  139. delete[] fix, delete[] blocked, delete[] used;
  140. }
  141. void add_edge(const int u, const int v){
  142. if(u == v){
  143. ans.push_back({u});
  144. return;
  145. }
  146. G[u][0].prev = G[u].back().next = (int)G[u].size();
  147. G[u].push_back((node){(int)G[u].size() - 1, 0, v});
  148. }
  149. int solve(bool _enumerate=true){
  150. scc();
  151. enumerate = _enumerate;
  152. for(int i = 0; i < V; ++i){
  153. vector<int> path, ver_list;
  154. dfs(i, i, path, ver_list);
  155. fix[i] = true;
  156. for(int j : ver_list){
  157. used[j] = blocked[j] = false, block_stack[j] = stack<int>();
  158. }
  159. }
  160. return count;
  161. }
  162. };
  163.  
  164. template<typename T> class segtree {
  165. private:
  166. int n,sz;
  167. vector<pair<T, int> > node;
  168. public:
  169. void resize(vector<T>& v){
  170. sz = (int)v.size();
  171. n = 1;
  172. while(n < sz){
  173. n *= 2;
  174. }
  175. node.resize(2*n);
  176. for(int i = 0; i < sz; i++){
  177. node[i+n] = make_pair(v[i], i);
  178. }
  179. for(int i=n-1; i>=1; i--){
  180. node[i] = min(node[2*i], node[2*i+1]);
  181. }
  182. }
  183. void update(int k, T a)
  184. {
  185. node[k+=n] = make_pair(a, k);
  186. while(k>>=1){
  187. node[k] = min(node[2*k], node[2*k+1]);
  188. }
  189. }
  190. pair<T, int> query(int a,int b)
  191. {
  192. pair<T, int> res1 = make_pair(numeric_limits<T>::max(), -1);
  193. pair<T, int> res2 = make_pair(numeric_limits<T>::max(), -1);
  194. a += n, b += n;
  195. while(a != b){
  196. if(a % 2) res1 = min(res1, node[a++]);
  197. if(b % 2) res2 = min(res2, node[--b]);
  198. a >>= 1, b >>= 1;
  199. }
  200. return min(res1, res2);
  201. }
  202. };
  203.  
  204. struct edge {
  205. int from, to, id;
  206. edge(const int _from, const int _to, const int _id)
  207. : from(_from), to(_to), id(_id){}
  208. };
  209.  
  210. class LCA{
  211. public:
  212. int V;
  213. vector<vector<int> > G;
  214. vector<int> ord,depth,id;
  215. segtree<int> st;
  216. LCA(int node_size) : V(node_size), G(V), depth(V), id(V, -1){}
  217. void add_edge(int from,int to){
  218. G[from].push_back(to),G[to].push_back(from);
  219. }
  220. void dfs(int u,int p,int k){
  221. id[u] = (int)ord.size();
  222. ord.push_back(u);
  223. depth[u] = k;
  224. for(int v : G[u]){
  225. if(v != p){
  226. dfs(v,u,k+1);
  227. ord.push_back(u);
  228. }
  229. }
  230. }
  231. void build(){
  232. ord.reserve(2*V-2);
  233. for(int i = 0; i < V; i++){
  234. if(id[i] < 0){
  235. dfs(i,-1,0);
  236. }
  237. }
  238. vector<int> stvec(2*V-2);
  239. for(int i = 0; i < 2*V-2; i++){
  240. stvec[i] = depth[ord[i]];
  241. }
  242. st.resize(stvec);
  243. }
  244. int solve(int u,int v){
  245. return ord[st.query(min(id[u],id[v]),max(id[u],id[v])+1).second];
  246. }
  247. int dist(int u,int v){
  248. int lca = solve(u,v);
  249. return depth[u] + depth[v] - 2*depth[lca];
  250. }
  251. pair<int, int> construct_virtual_tree(vector<int>& ver_list, unordered_map<int, int>& mapping);
  252. };
  253.  
  254. vector<pair<int, int> > es;
  255.  
  256. pair<int, int> LCA::construct_virtual_tree(vector<int>& ver_list, unordered_map<int, int>& mapping){
  257. const int n = (int)ver_list.size();
  258. sort(ver_list.begin(), ver_list.end(), [&](const int a, const int b){
  259. return id[a] < id[b];
  260. });
  261. stack<int> st;
  262. st.push(ver_list[0]), mapping[ver_list[0]] = 0;
  263. int id = n;
  264. for(int i = 0; i < n-1; ++i){
  265. const int u = solve(ver_list[i], ver_list[i+1]);
  266. if(u != ver_list[i]){
  267. int mapped_ver = mapping[st.top()];
  268. while(true){
  269. st.pop();
  270. if(st.empty() || depth[u] >= depth[st.top()]) break;
  271. const int tmp = mapping[st.top()];
  272. es.push_back({tmp, mapped_ver});
  273. mapped_ver = tmp;
  274. }
  275. if(st.empty() || st.top() != u){
  276. st.push(u), ver_list.push_back(u);
  277. es.push_back({id, mapped_ver});
  278. mapping[u] = id++;
  279. }else{
  280. es.push_back({mapping[u], mapped_ver});
  281. }
  282. }
  283. st.push(ver_list[i+1]), mapping[ver_list[i+1]] = i+1;
  284. }
  285. int mapped_ver = ((st.size() > 1) ? mapping[st.top()] : -1);
  286. while(st.size() > 1){
  287. st.pop();
  288. const int tmp = mapping[st.top()];
  289. es.push_back({tmp, mapped_ver});
  290. mapped_ver = tmp;
  291. }
  292. return {id, es.size()};
  293. }
  294.  
  295. vector<int> G[MAX_N];
  296. int visit[MAX_N];
  297. vector<P> ot;
  298. vector<int> ver_list;
  299.  
  300. void dfs(const int u, const int p, LCA& lca){
  301. visit[u] = 1;
  302. for(const int v : G[u]){
  303. if(v == p) continue;
  304. if(visit[v] == 0){
  305. lca.add_edge(u, v);
  306. dfs(v, u, lca);
  307. }else if(visit[v] == 1){
  308. ver_list.push_back(u), ver_list.push_back(v);
  309. ot.push_back({u, v});
  310. }
  311. }
  312. visit[u] = 2;
  313. }
  314.  
  315. int main()
  316. {
  317. cin.tie(0);
  318. ios::sync_with_stdio(false);
  319. int n, m;
  320. cin >> n >> m;
  321. rep(i, m){
  322. int a, b;
  323. cin >> a >> b;
  324. --a, --b;
  325. G[a].pb(b), G[b].pb(a);
  326. }
  327. if(m == n-1){
  328. cout << "0\n";
  329. return 0;
  330. }
  331. LCA lca(n);
  332. dfs(0, -1, lca);
  333. lca.build();
  334. zip(ver_list);
  335. unordered_map<int, int> mp;
  336. auto res = lca.construct_virtual_tree(ver_list, mp);
  337. int N = res.first, M = res.second;
  338. FindingAllCycles fac(N);
  339. for(const P& e : es){
  340. fac.add_edge(e.first, e.second), fac.add_edge(e.second, e.first);
  341. }
  342. for(const P& p : ot){
  343. const int u = mp[p.first], v = mp[p.second];
  344. fac.add_edge(u, v), fac.add_edge(v, u);
  345. ++M;
  346. }
  347. cout << (fac.solve(false) - M) / 2 << "\n";
  348. return 0;
  349. }
  350.  
Runtime error #stdin #stdout #stderr 0s 5908KB
stdin
Standard input is empty
stdout
Standard output is empty
stderr
terminate called after throwing an instance of 'std::length_error'
  what():  vector::reserve