噼里啪啦
我们学校的网线结构真神奇。有 n 台服务器编号 1~n,一些服务器直接连接IP 为 0 的网关,所有 n 台服务器网线相互连接。宁波来台风了!噼里啪啦~
一阵雷雨过后,我们发现很多服务器都无法访问了,为了评估破坏情况,我们觉得打开一些服务器随机 ping 其他服务器,然后记录不成功的情况。现在他需要一个程序分析记录,最少有几台服务器遭到雷电破坏。
贪心,先求一遍lca,然后根据lca的深度排序lca,从深往浅搜,然后如果用一个lca,那就把lca所在的子树都打上标记。如果后面求lca的时候,发现标记,就不把它计入ans。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 const int maxn=1e5+5, maxq=5e5+5; 6 7 inline int max(int x, int y){ return x<y?y:x; } 8 9 struct lca{ 10 int data, a, b, dep; 11 }q[maxq]; 12 bool operator <(const lca &x, const lca &y){ 13 return x.dep>y.dep; 14 } 15 16 class Graph{ 17 public: 18 struct Edge{ 19 Graph *belong; int to, next; 20 Edge& operator ++(){ *this=belong->edge[next]; return *this; } 21 int operator *(){ return to; } 22 }; 23 void reset(){ 24 edge[0].to=-1; 25 memset(fir, 0, sizeof(fir)); 26 cntedge=0; 27 } 28 void addedge(int x, int y){ 29 Edge &e=edge[++cntedge]; 30 e.belong=this, e.to=y; 31 e.next=fir[x], fir[x]=cntedge; 32 } 33 Edge get_link(int x){ return edge[fir[x]]; } 34 private: 35 int cntedge, fir[maxn]; 36 Edge edge[maxn]; 37 }; 38 39 int n, m, dep[maxn], son[maxn], size[maxn], fa[maxn]; 40 int times, top[maxn], dfn[maxn], cnt, L, R; 41 int seg[maxn*4], mark[maxn*4]; 42 Graph g; 43 44 void dfs1(int now, int par){ 45 int nc, maxsize=0; 46 for (Graph::Edge e=g.get_link(now); ~*e; ++e){ 47 nc=*e; 48 if (nc==par) continue; 49 fa[nc]=now; 50 dep[nc]=dep[now]+1; 51 dfs1(nc, now); 52 size[now]+=size[nc]; 53 if (size[nc]>maxsize){ 54 maxsize=size[nc]; 55 son[now]=nc; 56 } 57 } 58 ++size[now]; 59 } 60 61 void dfs2(int now, int par){ 62 int nc; 63 dfn[now]=++times; 64 if (son[now]){ //初始化! 65 top[son[now]]=top[now]; 66 dfs2(son[now], now); 67 } 68 for (Graph::Edge e=g.get_link(now); ~*e; ++e){ 69 nc=*e; 70 if (nc==par||nc==son[now]) continue; 71 top[nc]=nc; 72 dfs2(nc, now); 73 } 74 } 75 76 int prelca(int x, int y){ 77 while (top[x]!=top[y]){ 78 //这里要比较top谁高谁低! 79 if (dep[top[x]]>dep[top[y]]) x=fa[top[x]]; 80 else y=fa[top[y]]; 81 } 82 //这里是小于!!! 83 return dep[x]<dep[y]?x:y; 84 } 85 86 int query(int now, int l, int r){ 87 if (l>=L&&r<=R) return seg[now]; 88 if (mark[now]){ 89 seg[now<<1]=seg[now<<1|1]=seg[now]; 90 mark[now<<1]=mark[now<<1|1]=seg[now]; mark[now]=0; 91 } 92 int mid=(l+r)>>1, flag=0; 93 if (mid>=L) flag=max(query(now<<1, l, mid), flag); 94 if (mid<R) flag=max(query(now<<1|1, mid+1, r), flag); 95 return flag>0?1:0; 96 } 97 98 void modify(int now, int l, int r){ 99 if (l>=L&&r<=R){ seg[now]=1; mark[now]=1; return; } 100 if (mark[now]){ 101 seg[now<<1]=seg[now<<1|1]=seg[now]; 102 mark[now<<1]=mark[now<<1|1]=seg[now]; 103 } 104 int mid=(l+r)>>1; 105 if (mid>=L) modify(now<<1, l, mid); 106 if (mid<R) modify(now<<1|1, mid+1, r); 107 if (seg[now<<1]+seg[now<<1|1]) seg[now]=1; 108 } 109 110 int lalca(int x, int y){ 111 while (top[x]!=top[y]){ 112 if (dep[top[x]]>dep[top[y]]){ 113 L=dfn[top[x]], R=dfn[x]; 114 if (query(1, 1, n+1)>0) return -1; 115 x=fa[top[x]]; 116 } 117 else { 118 L=dfn[top[y]], R=dfn[y]; 119 if (query(1, 1, n+1)>0) return -1; 120 y=fa[top[y]]; 121 } 122 } 123 //最后也有可能断掉! 124 if (dep[x]>dep[y]){ 125 L=dfn[y], R=dfn[x]; 126 if (query(1, 1, n+1)>0) return -1; 127 } else { 128 L=dfn[x], R=dfn[y]; 129 if (query(1, 1, n+1)>0) return -1; 130 } 131 return dep[x]<dep[y]?x:y; 132 } 133 134 void init(){ 135 g.reset(); 136 times=0, cnt=0; 137 memset(size, 0, sizeof(size)); 138 memset(seg, 0, sizeof(seg)); 139 memset(mark, 0, sizeof(mark)); 140 memset(son, 0, sizeof(son)); 141 } 142 143 int main(){ 144 int t; 145 scanf("%d", &t); 146 int x, y; 147 for (int tt=0; tt<t; ++tt){ 148 init(); 149 scanf("%d", &n); 150 for (int i=0; i<n; ++i){ 151 scanf("%d%d", &x, &y); 152 g.addedge(x, y); 153 g.addedge(y, x); 154 } 155 dfs1(0, -1); 156 dfs2(0, -1); 157 scanf("%d", &m); 158 for (int i=0; i<m; ++i){ 159 scanf("%d%d", &x, &y); 160 q[i].a=x; 161 q[i].b=y; 162 q[i].dep=dep[prelca(x, y)]; 163 } 164 sort(q, q+m); 165 int result, ans=0; 166 for (int i=0; i<m; ++i){ 167 result=lalca(q[i].a, q[i].b); 168 if (!~result) continue; 169 else { 170 L=dfn[result], R=dfn[result]+size[result]-1; 171 modify(1, 1, n+1); 172 ++ans; 173 } 174 } 175 printf("Case #%d: %d\n", tt+1, ans); 176 } 177 return 0; 178 }