标签:mem 自己 clear blank get main 好的 题意 class
http://acm.hdu.edu.cn/showproblem.php?pid=6203
题意:
n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V
无法连通。问无法通行的点最少有多少个。
思路:
贪心思维,破坏两个点的LCA是最佳的。那么怎么判断现在在(u,v)之间的路径上有没有被破坏的点呢,如果没有的话那么此时就要破坏这个lca点。一开始我们要把询问按照u和v的lca深度从大到小排序,如果某个点需要被破坏,那么它的所有子节点都可以不再需要破坏别的点了(因为它的子节点到别的子节点肯定是要经过该点的,要注意这个前提是lca是排好序的,自己脑补一下~)。
所以,用dfs序来维护子节点是最好的,记录in和out两个数组。然后用树状数组来维护。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<sstream> 6 #include<vector> 7 #include<stack> 8 #include<queue> 9 #include<cmath> 10 #include<map> 11 #include<set> 12 using namespace std; 13 typedef long long ll; 14 typedef pair<int,ll> pll; 15 const int INF = 0x3f3f3f3f; 16 const int maxn = 1e4+5; 17 18 int n; 19 int Log; 20 int dfs_clock; 21 int in[maxn],out[maxn]; 22 int deep[maxn]; 23 int p[maxn][100]; 24 int c[2*maxn]; 25 vector<int> G[maxn]; 26 27 struct node 28 { 29 int u,v,lca; 30 }query[50005]; 31 32 void dfs(int u, int fa, int d) 33 { 34 in[u]=++dfs_clock; 35 deep[u]=d; 36 p[u][0]=fa; 37 for(int i=0;i<G[u].size();i++) 38 { 39 int v=G[u][i]; 40 if(v==fa) continue; 41 dfs(v,u,d+1); 42 } 43 out[u]=++dfs_clock; 44 } 45 46 47 bool cmp(node a, node b) 48 { 49 return deep[a.lca]>deep[b.lca]; 50 } 51 52 53 void init() 54 { 55 for(int j=1;j<=Log;j++) 56 for(int i=1;i<=n;i++) 57 p[i][j]=p[p[i][j-1]][j-1]; 58 } 59 60 61 int LCA(int x, int y) 62 { 63 if(x==y) return x; 64 if(deep[x]<deep[y]) swap(x,y); 65 for(int i=Log;i>=0;i--) 66 { 67 if(deep[p[x][i]]>=deep[y]) 68 x=p[x][i]; 69 } 70 if(x==y) return x; 71 for(int i=Log;i>=0;i--) 72 { 73 if(p[x][i]!=p[y][i]) 74 { 75 x=p[x][i];y=p[y][i]; 76 } 77 } 78 return p[x][0]; 79 } 80 81 int lowbit(int x) 82 { 83 return x&(-x); 84 } 85 86 int sum(int x) 87 { 88 int ret = 0; 89 while(x>0) 90 { 91 ret+=c[x]; 92 x-=lowbit(x); 93 } 94 return ret; 95 } 96 97 void add(int x, int d) 98 { 99 while(x<=2*n) 100 { 101 c[x]+=d; 102 x+=lowbit(x); 103 } 104 } 105 106 int main() 107 { 108 //freopen("in.txt","r",stdin); 109 while(~scanf("%d",&n)) 110 { 111 dfs_clock=0; 112 memset(c,0,sizeof(c)); 113 memset(p,0,sizeof(p)); 114 for(int i=0;i<=n+1;i++) G[i].clear(); 115 for(int i=0;i<n;i++) 116 { 117 int u,v; 118 scanf("%d%d",&u,&v); 119 u++;v++; 120 G[u].push_back(v); 121 G[v].push_back(u); 122 } 123 n++; 124 for(Log=0;(1<<Log)<=n;Log++); 125 Log--; 126 127 dfs(1,1,1); 128 init(); 129 int q; 130 scanf("%d",&q); 131 for(int i=1;i<=q;i++) 132 { 133 scanf("%d%d",&query[i].u,&query[i].v); 134 query[i].u++;query[i].v++; 135 query[i].lca=LCA(query[i].u,query[i].v); 136 } 137 sort(query+1,query+q+1,cmp); 138 int ans=0; 139 for(int i=1;i<=q;i++) 140 { 141 int u=query[i].u,v=query[i].v,lca=query[i].lca; 142 int tmp1=sum(in[u]),tmp2=sum(in[v]); 143 if(sum(in[u])+sum(in[v])) continue; 144 else 145 { 146 ans++; 147 add(in[lca],1); 148 add(out[lca],-1); 149 } 150 } 151 printf("%d\n",ans); 152 } 153 return 0; 154 }
HDU 6203 ping ping ping(dfs序+LCA+树状数组)
标签:mem 自己 clear blank get main 好的 题意 class
原文地址:http://www.cnblogs.com/zyb993963526/p/7554692.html