1 #include <iostream>
2 #include <cstring>
3 #include <cstdio>
4 using namespace std;
5
6 typedef long long ll;
7 const int maxn = 1e5 + 5;
8 const int maxm = 5e5 + 5;
9 int dfn[maxn], low[maxn], head[maxn];
10 ll ans[maxn], siz[maxn];
11 int n, m, tot, num, root;
12 bool cut[maxn];
13 struct edge{
14 int to, next;
15 } ed[2*maxm];
16 inline void init(){
17 memset( head, -1, sizeof(head) );
18 memset( dfn, 0, sizeof(dfn) );
19 memset( cut, false, sizeof(cut) );
20 memset( ans, 0, sizeof(ans) );
21 num = 0;
22 tot = 1;
23 }
24
25 inline int min( int a, int b ){
26 return a<b ? a:b;
27 }
28
29 inline void add( int u, int v ){
30 tot ++;
31 ed[tot].to = v;
32 ed[tot].next = head[u];
33 head[u] = tot;
34 }
35
36 inline void tarjan( int u ){
37 dfn[u] = low[u] = ++num;
38 siz[u] = 1;
39 int flag = 0, sum = 0;
40 for( int i=head[u]; i!=-1; i=ed[i].next ){
41 int v = ed[i].to;
42 if( !dfn[v] ){
43 tarjan(v);
44 siz[u] += siz[v]; //计算子树的点个数
45 low[u] = min(low[u], low[v]);
46 if( dfn[u]<=low[v] ){
47 flag ++;
48 ans[u] += (ll)siz[v]*(n-siz[v]); //if(cut[i]) ans = (i的子树, 除该子树的其他部分)的点对和
49 sum += siz[v];
50 if( u!=root || flag>1 ) cut[u] = true;
51 }
52 }else low[u] = min(low[u], dfn[v]);
53 }
54 if( cut[u] ) ans[u] += (ll)(n-sum-1)*(sum+1) + (n-1); //如果去掉的点i是割点ans继续累加上(其他部分,i和i的子树)点对 + (i, 除i的其他部分)点对
55 else ans[u] = 2*(n-1); //if(!cut[i]) ans = 2*(n-1)
56 }
57
58 int main(){
59 scanf("%d%d", &n, &m);
60 init();
61 for( int i=0; i<m; i++ ){
62 int u, v;
63 scanf("%d%d", &u, &v);
64 add( u, v );
65 add( v, u );
66 }
67 root = 1;
68 tarjan(1);
69 for( int i=1; i<=n; i++ )
70 printf("%lld\n", ans[i]);
71
72 return 0;
73 }
74 /*Sample Input
75 5 5
76 1 2
77 2 3
78 1 3
79 3 4
80 4 5
81 Sample Output
82 8
83 8
84 16
85 14
86 8
87 */