C
这里用了map存缩点后的边,会慢很多
一个比较显而易见的性质:对于v节点的所有ui节点(ui向v连边),都有dist[ui]相等。
所以对于这些dist应该相等的点缩点,然后最长路,之后dis之差就是该点点权了
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const int N=2e5+10;
vector<int>E[N],invE[N];
int p[N],dist[N];
bool st[N],vis[N];
int Find(int x)
{
if(x!=p[x])return p[x]=Find(p[x]),p[x];
return x;
}
map<int,int>nwE[N];
int dfs(int u)
{
if(st[u])return 1;
if(vis[u])return 0;
st[u]=1;
for(auto [v,t]:nwE[u])
{
if(dfs(v))return 1;
}
st[u]=0;
vis[u]=1;
return 0;
}
int color[N];
using pii=pair<int,int>;
int rs[N];
void dijkstra()
{
dist[1]=1;
priority_queue<pii>heap;
heap.push({1,1});
while(heap.size())
{
auto [dis,u]=heap.top();heap.pop();
for(auto [v,t]:nwE[u])
{
if(!t)continue;
if(dist[v]<dist[u]+1)
{
dist[v]=dist[u]+1;
heap.push({dist[v],v});
}
}
}
queue<int>q;
q.push(1);
rs[1]=1;
while(q.size())
{
int u=q.front();q.pop();
if(st[u])continue;st[u]=1;
for(auto v:E[u])
{
{
rs[v]=dist[Find(v)]-dist[Find(u)];
q.push(v);
}
}
}
}
void solve()
{
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)E[i].clear(),invE[i].clear(),nwE[i].clear(),
st[i]=0,vis[i]=0,color[i]=-1;
memset(dist,0,sizeof(dist[0])*(n+1));
for(int i=1,u,v;i<=m;++i)
{
scanf("%d%d",&u,&v);
E[u].push_back(v);
invE[v].push_back(u);
}
if(n==1){cout<<"YES\n1\n"<<endl;return ;}
for(int i=1;i<=n;++i)p[i]=i;
for(int i=1;i<=n;++i)
if(invE[i].size())
{
int t=invE[i][0];
for(auto v:invE[i])
p[Find(v)]=p[Find(t)];
}
for(int i=1;i<=n;++i)
{
for(auto v:E[i])
nwE[Find(i)][Find(v)]=1;
}
for(int i=1;i<=n;++i)
for(auto v:E[i])
{
if(Find(i)==Find(v)){printf("No\n");return ;}
}
if(dfs(1)){printf("No\n");return ;}
printf("Yes\n");
memset(st,0,sizeof(st[0])*(n+1));
dijkstra();
for(int i=1;i<=n;++i)printf("%d%c",rs[i]," \n"[i==n]);
}
int main()
{
int T;scanf("%d",&T);
while(T--)solve();
}
M
考虑数位背包
#include<bits/stdc++.h>
using namespace std;
const int P=1e9+7,N=1e3+10;
using ll=long long;
ll finv[N],fac[N];
ll POW(ll x,int k=P-2,ll rs=1){while(k){if(k&1)rs=rs*x%P;x=x*x%P;k>>=1;}return rs;}
void init()
{
finv[1]=finv[0]=fac[0]=1;
for(int i=1;i<N;++i)fac[i]=fac[i-1]*i%P;
finv[N-1]=POW(fac[N-1]);
for(int i=N-2;i;--i)finv[i]=finv[i+1]*(i+1)%P;
}
ll C(int a,int b)
{
if(b>a||a<0||b<0)return 0;
return fac[a]*finv[a-b]%P*finv[b]%P;
}
ll dp[55][20][257];
int a[55];
const int Mx=162;
ll dfs(int pos,ll cnt,ll r,ll &n,ll&k)
{
if(pos==-1)return r==0;
if(r>=Mx)return 0;
if(r<0)return 0;
ll &rs=dp[pos][cnt][r];
if(~rs)return rs;
rs=0;
int x=(pos==0?0:((n>>pos-1)&1));
if(!a[pos])
{
for(int i=0;i<=k-cnt;++i)
rs+=C(k-cnt,i)*dfs(pos-1,cnt,(r-i*(k-i)<<1)|x,n,k)%P;
}
else
{
for(int i=0;i<=cnt;++i)
for(int j=0;j<=k-cnt;++j)
rs+=C(k-cnt,j)*C(cnt,i)%P*dfs(pos-1,i,(r-(i+j)*(k-i-j))<<1|x,n,k)%P;
}
return rs%=P,rs;
}
ll cal(ll n,ll m,ll k)
{
int pos=-1;
memset(dp,-1,sizeof(dp));
while(m)a[++pos]=m&1,m>>=1;
ll r=0;
for(int i=pos+1;i<=50;++i)
if(n>>i&1)r+=1ll<<(i-pos-1);
return dfs(pos+1,k,r,n,k);
}
int main()
{
init();
ll n,m,k;scanf("%lld%lld%lld",&n,&m,&k);
printf("%lld\n",cal(n,m,k));
}