2018 icpc 徐州现场赛G-树上差分+组合数学-大佬的代码

现场赛大佬打印的代码,观摩了一哈。

写了注释,贴一下,好好学习。%%%PKU

 

代码:

  1 //树上差分(LCA)
  2 #include<bits/stdc++.h>
  3 
  4 #define For(i,x,y) for (int i=x;i<y;i++)
  5 #define fi first
  6 #define se second
  7 #define pb push_back
  8 #define mp make_pair
  9 #define lf else if
 10 
 11 #define dprintf(...) fprintf(stderr,__VA_ARGS__)
 12 using namespace std;
 13 
 14 typedef long long ll;
 15 typedef double db;
 16 typedef pair<int,int> pii;
 17 typedef vector<int> Vi;
 18 
 19 int IN(){//读入挂
 20     int c,f,x;
 21     while (!isdigit(c=getchar())&&c!='-');c=='-'?(f=1,x=0):(f=0,x=c-'0');
 22     while (isdigit(c=getchar())) x=(x<<1)+(x<<3)+c-'0';return !f?x:-x;
 23 }
 24 
 25 const int p=1e9+7;
 26 const int N=3e5+19;
 27 
 28 int Pow(int a,int b){//快速幂
 29     int res=1;
 30     for (;b;b>>=1,a=1ll*a*a%p) if (b&1) res=1ll*res*a%p;
 31     return res;
 32 }
 33 
 34 struct Edge{
 35     int y,nxt;
 36 } E[N*2];
 37 int fac[N],inv[N];
 38 int las[N],fa[20][N],A[N],B[N],dep[N];
 39 int n,m,cnt,x,y,z,ans,k;
 40 
 41 int C(int n,int m){//组合数
 42     if (n<m) return 0;
 43     return 1ll*fac[n]*inv[m]%p*inv[n-m]%p;
 44 }
 45 
 46 void Link(int x,int y){//链式前向星存图
 47     E[cnt]=(Edge){y,las[x]};las[x]=cnt++;
 48     E[cnt]=(Edge){x,las[y]};las[y]=cnt++;
 49 }
 50 
 51 void dfs(int x){//LCA的dfs
 52     for (int i=las[x],y;~i;i=E[i].nxt)
 53         if ((y=E[i].y)!=fa[0][x]){
 54             fa[0][y]=x;
 55             dep[y]=dep[x]+1;
 56             dfs(y);
 57         }
 58 }
 59 
 60 int LCA(int x,int y){//LCA(ST)
 61     if (dep[x]>dep[y]) swap(x,y);
 62     for (int i=dep[y]-dep[x],k=0;i;i>>=1,k++) if(i&1) y=fa[k][y];
 63     if(x==y) return x;
 64     for (int i=19;~i;i--) if (fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y];
 65     return fa[0][x];
 66 }
 67 
 68 void Dfs(int x){//树上差分的dfs,从根节点深搜,回溯时将其本身的权值加上所有子节点的权值
 69     for (int i=las[x],y;~i;i=E[i].nxt)
 70         if ((y=E[i].y)!=fa[0][x]){//筛掉父节点
 71             Dfs(y);
 72             A[x]+=A[y];//累加权值和
 73             B[x]+=B[y];
 74         }
 75 }
 76 
 77 void Main(){
 78     n=IN(),m=IN(),k=IN();
 79     For(i,1,n+1) las[i]=-1,A[i]=B[i]=0;
 80     cnt=0;
 81     For(i,1,n) Link(IN(),IN());
 82     dfs(1);
 83     For(i,1,20) For(x,1,n+1) fa[i][x]=fa[i-1][fa[i-1][x]];
 84     For(i,1,m+1){
 85         x=IN(),y=IN();
 86         z=LCA(x,y);
 87         A[x]++,A[y]++,A[z]--,A[fa[0][z]]--;
 88         B[x]++,B[y]++,B[z]-=2;//起点终点权值+1,lca权值-2
 89     }
 90     Dfs(1);
 91     ans=0;
 92 //    cout<<"--------"<<endl;
 93 //    for(int i=1;i<=n;i++)
 94 //        cout<<i<<" "<<A[i]<<endl;
 95 //    cout<<"--------"<<endl;
 96 //    for(int i=2;i<=n;i++)
 97 //        cout<<i<<" "<<B[i]<<endl;
 98 //    cout<<"--------"<<endl;
 99     For(i,1,n+1){
100         ans=(ans+C(A[i],k))%p;
101     }
102     For(i,2,n+1){
103         ans=(ans-C(B[i],k)+p)%p;
104     }
105     printf("%d\n",ans);
106 }
107 
108 int main(){
109     fac[0]=1;
110     For(i,1,N) fac[i]=1ll*fac[i-1]*i%p;
111     inv[N-1]=Pow(fac[N-1],p-2);
112     for(int i=N-1;i;i--) inv[i-1]=1ll*inv[i]*i%p;
113     for(int T=IN();T--;) Main();
114 }
115 
116 /*
117 1
118 3 6 2
119 1 2
120 1 3
121 1 1
122 2 2
123 3 3
124 1 2
125 1 3
126 2 3
127 */

 

 

 

 

OK.

posted @ 2018-11-03 20:45  ZERO-  阅读(441)  评论(0编辑  收藏  举报