有N个点,M条边组成的无向图,现在我们想知道删除一个点u,它会使得哪些x、y对,不能从x到达y,求对于每个点这样的<x,y>对的个数。
于是,很明显的就是,我们可以将它缩点成为一个广义圆方树,然后在树上跑就是了。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <string> 5 #include <cstring> 6 #include <algorithm> 7 #include <limits> 8 #include <vector> 9 #include <stack> 10 #include <queue> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 #include <unordered_map> 15 #include <unordered_set> 16 #define lowbit(x) ( x&(-x) ) 17 #define pi 3.141592653589793 18 #define e 2.718281828459045 19 #define INF 0x3f3f3f3f 20 #define HalF (l + r)>>1 21 #define lsn rt<<1 22 #define rsn rt<<1|1 23 #define Lson lsn, l, mid 24 #define Rson rsn, mid+1, r 25 #define QL Lson, ql, qr 26 #define QR Rson, ql, qr 27 #define myself rt, l, r 28 #define pii pair<int, int> 29 #define MP(a, b) make_pair(a, b) 30 using namespace std; 31 typedef unsigned long long ull; 32 typedef unsigned int uit; 33 typedef long long ll; 34 const int maxN = 1e5 + 7, maxM = 1e6 + 7; 35 int N, M, head[maxN], cnt; 36 struct Eddge 37 { 38 int nex, to; 39 Eddge(int a=-1, int b=0):nex(a), to(b) {} 40 } edge[maxM]; 41 inline void addEddge(int u, int v) 42 { 43 edge[cnt] = Eddge(head[u], v); 44 head[u] = cnt++; 45 } 46 inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); } 47 int dfn[maxN], low[maxN], tot, Stap[maxN], Stop; 48 int n; 49 bool iscut[maxN] = {false}; 50 vector<int> V, to[maxN << 1]; 51 void Tarjan(int u, int fa) 52 { 53 int child = 0; 54 V.push_back(u); 55 dfn[u] = low[u] = ++tot; 56 Stap[++Stop] = u; 57 for(int i=head[u], v; ~i; i=edge[i].nex) 58 { 59 v = edge[i].to; 60 if(v == fa) continue; 61 if(!dfn[v]) 62 { 63 child++; 64 Tarjan(v, u); 65 low[u] = min(low[u], low[v]); 66 if(low[v] >= dfn[u]) 67 { 68 iscut[u] = true; 69 if(low[v] == dfn[u]) 70 { 71 int p; ++n; 72 do 73 { 74 p = Stap[Stop--]; 75 to[p].push_back(n); 76 to[n].push_back(p); 77 } while(p ^ v); 78 to[u].push_back(n); 79 to[n].push_back(u); 80 } 81 else 82 { 83 Stop--; 84 to[u].push_back(v); 85 to[v].push_back(u); 86 } 87 } 88 } 89 else low[u] = min(low[u], dfn[v]); 90 } 91 if(!fa && child <= 1) iscut[u] = false; 92 } 93 ll ans[maxN] = {0}, siz[maxN << 1], all; 94 void dfs(int u, int fa) 95 { 96 siz[u] = u <= N; 97 for(int v : to[u]) 98 { 99 if(v == fa) continue; 100 dfs(v, u); 101 siz[u] += siz[v]; 102 } 103 if(u <= N) 104 { 105 ans[u] = 2LL * (all - 1); 106 if(iscut[u]) 107 { 108 for(int v : to[u]) 109 { 110 if(v == fa) 111 { 112 ans[u] += (all - siz[u]) * (siz[u] - 1LL); 113 } 114 else 115 { 116 ans[u] += siz[v] * (all - siz[v] - 1); 117 } 118 } 119 } 120 } 121 } 122 inline void init() 123 { 124 cnt = 0; 125 for(int i=1; i<=N; i++) head[i] = -1; 126 } 127 int main() 128 { 129 scanf("%d%d", &N, &M); n = N; 130 init(); 131 for(int i=1, u, v; i<=M; i++) 132 { 133 scanf("%d%d", &u, &v); 134 _add(u, v); 135 } 136 for(int i=1; i<=N; i++) 137 { 138 if(!dfn[i]) 139 { 140 V.clear(); 141 Tarjan(i, 0); 142 all = V.size(); 143 dfs(i, 0); 144 } 145 } 146 for(int i=1; i<=N; i++) printf("%lld\n", ans[i]); 147 return 0; 148 }