求 hack
查看原帖
求 hack
416975
sbno333楼主2024/12/7 22:59

rt,思路和题解都不一样,赛场想的,怀疑自己的证明是假的。

考虑菊花,其实就是边组成的完全图,树就是若干完全图,然后完全图直间共用点,考虑到如果初始节点定了,这些完全图像菊花一样左端点就定了(因为从初始到这个完全图上任意节点,第一个节点可以确定),所以就是每个完全图不合法方案的乘积,考虑 dfs 序中进行,每个完全图初始节点改一次,贡献改一次,这样可以线性扫。

感觉没啥问题,但是代码只能过 k=1k=1 和菊花图和链。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define mod 1000000007ll
struct bi{
    int u,v;
}ss[1000009],zs[1000009];
int jc[1000009];
int ksm(int a,int b){
    int ans;
    ans=1;
    while(b){
        if(b&1){
            ans*=a;
            ans%=mod;
        }
        a*=a;
        a%=mod;
        b>>=1;
    }
    return ans;
}
int dfn[1000009];
int nfd[1000009];
struct st{
    int v,ne;
}sd[1000009];
int h[1000009];
int inn;
void add(int u,int v){
    sd[++inn].v=v;
    sd[inn].ne=h[u];
    h[u]=inn;
}
int de,ans;
int ds[1000009];
int rr[1000009];
int bb[1000009];
void dfs(int t,int fa){
    dfn[++inn]=t;
    nfd[t]=inn;
    int zz;
    zz=inn;
    for(int i=h[t];i;i=sd[i].ne){
        if(sd[i].v!=fa)
        dfs(sd[i].v,t);
    }
    rr[zz]=inn;
}

bool cmp(int x,int y){
    return ss[x].u==ss[y].u?ss[x].v<ss[y].v:ss[x].u<ss[y].u;
}
bool cmp2(bi a1,bi a2){
    return a1.v==a2.v?a1.u<a2.u:a1.v<a2.v;
}
int bj[1000009];
vector<int> g[1000009];
int nn[1000009];
int ggg;int n,k;
int xa,xb;
void ddfs(int t,int &rw,int fa){
    if(ss[bb[rw]].v==t){
        ans+=ggg-de;
        ans+=mod;
        ans%=mod;
        rw++;
    }
    if(ss[bb[rw]].v<t||ss[bb[rw]].v>rr[t]||rw>k){
    	return;
	} 
    for(int i=1;i<=nn[t];i++){
        if(ss[bb[rw]].v>=g[t][i]&&ss[bb[rw]].v<=rr[g[t][i]]&&g[t][i]!=fa){
        	if(t!=xa||g[t][i]!=xb){
        		bj[t]++;
            if(bj[t]==1){
                de*=ksm(ds[t]-1,mod-2);
                de%=mod;
            }else{
                de*=ksm(bj[t]-1,mod-2);
                de%=mod;
                de*=bj[t];
                de%=mod;
            }
			}
            
            ddfs(g[t][i],rw,t);
        }
    }
}
int ssd[1000009];
void _main(){
    inn=0;
    cin>>n>>k;
    for(int i=1;i<=n;i++){
        h[i]=dfn[i]=ds[i]=ssd[i]=0;
        g[i].push_back(0);
        nn[i]=0;
        nfd[i]=0;
        ggg=0;
        bj[i]=0;
        bb[i]=rr[i]=0;
    }

    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        ss[i]={u,v};
        add(u,v),add(v,u);
        ssd[u]++;
        ssd[v]++;
    }
	for(int i=1;i<=k;i++){
        cin>>bb[i];
    }
    inn=0;
    if(ssd[ss[bb[k]].u]!=1)
    dfs(ss[bb[k]].u,0);
    else
    dfs(ss[bb[k]].v,0);
    k--;
    for(int i=1;i<n;i++){
        ss[i].u=nfd[ss[i].u];
        ss[i].v=nfd[ss[i].v];
        if(ss[i].u>ss[i].v){
            swap(ss[i].u,ss[i].v);
        }
        ds[ss[i].u]++,ds[ss[i].v]++;
    }
	for(int i=1;i<n;i++){
		zs[i]=ss[i];
	}
    sort(zs+1,zs+n,cmp2);
    for(int i=1;i<n;i++){
        int x,y;
        x=zs[i].u,y=zs[i].v;
        if(x>y){
        	swap(x,y);
		}
        g[x].push_back(0);
        g[x][++nn[x]]=y;
    }
    
    sort(bb+1,bb+1+k,cmp);
    
    ans=1;
    for(int i=1;i<=n;i++){
        ans*=jc[ds[i]-1];
        ans%=mod;
    }
    ggg=ans;
    de=ans;
    for(int i=1;i<=n;i++){
        bj[i]=0;
    }
    int rw;
    rw=1;
    xa=ss[bb[k+1]].u,xb=ss[bb[k+1]].v;
    ddfs(1,rw,0);
    cout<<ans<<endl;
}
signed main(){
    std::ios::sync_with_stdio(0);
   
    jc[0]=1;
    for(int i=1;i<=1000000;i++){
        jc[i]=jc[i-1]*i%mod;
    }
    int c,t;
    cin>>c>>t;
    while(t--){
        _main();
    }
    return 0;
}
2024/12/7 22:59
加载中...