标签:
由于每条边的权值都为1,所以最短路bfs就够了,只是要求转置图的最短路,所以得用两个set来维护,一个用来存储上次扩散还没访问的点,一个用来存储这一次扩散还没访问的点。
算法:bfs+set
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<string.h> 5 #include<queue> 6 #include<vector> 7 #include<stack> 8 #include<set> 9 using namespace std; 10 const int maxn=200100; 11 const int INF=0x3f3f3f3f; 12 int t,n,m,u,v; 13 int head[maxn];int tot; 14 int di[maxn]; 15 struct Edge 16 { 17 int to,next; 18 }edge[maxn]; 19 void init() 20 { 21 tot=0; 22 memset(head,-1,sizeof(head)); 23 } 24 void add(int u,int v) 25 { 26 edge[tot].to=v; 27 edge[tot].next=head[u]; 28 head[u]=tot++; 29 } 30 struct node 31 { 32 int num,dis; 33 }; 34 35 void bfs(int beg) 36 { 37 set<int>s,e; 38 set<int>::iterator it; 39 queue<node>q; 40 for(int i=1;i<=n;i++) 41 s.insert(i),di[i]=INF; 42 node temp,nex; 43 temp.num=beg,temp.dis=0; 44 q.push(temp); 45 s.erase(beg); 46 while(!q.empty()) 47 { 48 temp=q.front();q.pop(); 49 for(int i=head[temp.num];i!=-1;i=edge[i].next) 50 { 51 int v=edge[i].to; 52 if(s.find(v)==s.end()) 53 continue; 54 s.erase(v);e.insert(v); 55 } 56 for(it=s.begin();it!=s.end();it++) 57 { 58 nex.num=*it;nex.dis=temp.dis+1; 59 di[nex.num]=min(nex.dis,di[nex.num]); 60 q.push(nex); 61 } 62 s.swap(e);e.clear(); 63 } 64 } 65 int main() 66 { 67 //freopen("input.txt","r",stdin); 68 scanf("%d",&t); 69 while(t--) 70 { 71 scanf("%d%d",&n,&m); 72 init(); 73 for(int i=0;i<m;i++){ 74 scanf("%d%d",&u,&v); 75 add(u,v); 76 add(v,u); 77 } 78 int pos; 79 scanf("%d",&pos); 80 bfs(pos); 81 if(n!=pos){ 82 for(int i=1;i<=n;i++) 83 { 84 if(i==pos)continue; 85 if(i!=n) 86 printf("%d ",di[i]!=INF?di[i]:-1); 87 else 88 printf("%d\n",di[i]!=INF?di[i]:-1); 89 } 90 91 }else{ 92 for(int i=1;i<=n-2;i++) 93 { 94 if(1!=(n-1)) 95 printf("%d ",di[i]!=INF?di[i]:-1); 96 else 97 printf("%d\n",di[i]!=INF?di[i]:-1); 98 } 99 100 } 101 } 102 return 0; 103 }
题意是要求所有节点的权值与其祖先节点权值相乘小于或等于k的总共有多少对,一开始知道必须得进行dfs,也知道可以马上建一个数组b[n]来记录每个节点需要和小于多少的数相乘才会小于看,但是在查询有多少个祖先节点小于b[i]时没有找到方法,后来才知道,可以将数据离散化后存进树状数组,只保留当前节点的父节点在树状数组当中,一旦离开这个节点,就把这个节点的权值在树状数组中删除
算法:dfs+离散化+BIT
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<string.h> 5 #include<vector> 6 #include<queue> 7 #include<stack> 8 using namespace std; 9 #define ll long long 10 const int maxn=100100; 11 int n; 12 ll k,a[maxn]; 13 vector<int>son[maxn]; 14 ll ran[maxn]; 15 ll b[maxn]; 16 int in[maxn]; 17 ll B[maxn]; 18 int low_bit(int x) 19 { 20 return x&(-x); 21 } 22 ll Sum(int x){ 23 ll s1 = 0; 24 while (x) s1 += B[x], x -= low_bit(x); 25 return s1; 26 } 27 void Add(int x, int d){ 28 while (x<=n) B[x] += d,x += low_bit(x); 29 } 30 void init(int n) 31 { 32 for(int i=1;i<=n;i++){ 33 son[i].clear(); 34 } 35 memset(in,0,sizeof(in)); 36 } 37 ll dfs(int rt) 38 { 39 Add(ran[rt],1); 40 ll ans=0; 41 for(int i=0;i<son[rt].size();i++){ 42 int nex=son[rt][i]; 43 ans+=dfs(nex); 44 } 45 Add(ran[rt], -1); 46 ll num=upper_bound(a+1,a+1+n,b[rt])-a-1; 47 ans+=Sum(num); 48 return ans; 49 } 50 int main() 51 { 52 //freopen("input.txt","r",stdin); 53 int t; scanf("%d", &t); 54 while(t--) 55 { 56 scanf("%d%lld",&n,&k); 57 init(n); 58 for(int i=1;i<=n;i++){ 59 scanf("%lld",&a[i]); 60 ran[i] = a[i]; 61 if (a[i] != 0) 62 b[i] = k / a[i]; 63 else 64 b[i] = 0; 65 } 66 67 int u,v; 68 for(int i=1;i<=n-1;i++){ 69 scanf("%d%d",&u,&v); 70 son[u].push_back(v); 71 in[v]++; 72 } 73 sort(a+1,a+1+n); 74 unique(a+1,a+1+n); 75 for(int i=1;i<=n;i++){ 76 ran[i]=lower_bound(a+1,a+n+1,ran[i])-a; 77 } 78 int root=1; 79 for(int i=1;i<=n;i++){ 80 if(in[i]==0) 81 root=i; 82 } 83 ll ans=dfs(root); 84 printf("%lld\n",ans); 85 } 86 return 0; 87 }
2016 ACM/ICPC Asia Regional Dalian Online
标签:
原文地址:http://www.cnblogs.com/dgutfly/p/5874406.html