P7422 题解
P7422 题解
首先观察题目中的限制,不难发现
观察两个要求,对于第一个,供应材料不同的限制比较好满足,城市
第二个要求,
显然只需要对于圆点统计答案,设点 不难发现只有在合并到叶子节点的时候才会要用 然后就开了两个G的数组,事实上 std 最开始公开时的版本也 MLE 了。
当然把数组开小一点就可以解决了,不过貌似需要精打细算一下,而且赛时由于我开炸的太多了所以没有想优化,因此我使用了一个空间更加安全的做法。
由于对于每个点进行
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
const int p=998244353;
#define rint register int
#define ll long long
#define rll register long long
template<typename T> void read(T &x){
x=0;rint f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
x*=f;
}
vector<int> g[N];
struct Edge{
int to,nxt;
}e[N<<1];
int h[N],idx;
void Ins(rint a,rint b){
e[++idx].to=b;e[idx].nxt=h[a];h[a]=idx;
}
int n,m,k,fang,c[N];
map<int,int> mp;
int low[N],dfn[N],stk[N],tp,Time;
void tarjan(rint u,rint fa){
dfn[u]=low[u]=++Time;
stk[++tp]=u;
for(rint v:g[u]){
if(v==fa)continue;
if(!dfn[v]){
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]){
++fang;
while(1){
rint x=stk[tp--];
Ins(fang,x);Ins(x,fang);
if(x==v)break;
}
Ins(fang,u);Ins(u,fang);
}
}else low[u]=min(low[u],dfn[v]);
}
}
int dp[30];
ll res;
int top[N],siz[N],fa[N],son[N],d[N],dis[N];
void dfs1(rint u){
dfn[u]=++Time;siz[u]=1;dis[u]+=u<=n;
for(rint i=h[u];i;i=e[i].nxt){
rint v=e[i].to;
if(v==fa[u])continue;
d[v]=d[u]+1;
fa[v]=u;dis[v]=dis[u];
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])son[u]=v;
}
}
void dfs2(rint u,rint t){
top[u]=t;
if(son[u])dfs2(son[u],t);
for(rint i=h[u];i;i=e[i].nxt){
rint v=e[i].to;
if(v==fa[u]||v==son[u])continue;
dfs2(v,v);
}
h[u]=0;
}
int lca(rint x,rint y){
while(top[x]^top[y]){
if(d[top[x]]<d[top[y]])y=fa[top[y]];
else x=fa[top[x]];
}
return d[x]>d[y]?y:x;
}
int colcnt,col;
bool cmp(rint a,rint b){
return dfn[a]<dfn[b];
}
void insert(rint x){
if(!tp){
stk[++tp]=x;
return ;
}
rint lc=lca(stk[tp],x);
while(tp>1&&d[stk[tp-1]]>=d[lc])
Ins(stk[tp-1],stk[tp]),tp--;
if(stk[tp]!=lc)
Ins(lc,stk[tp]),stk[tp]=lc;
stk[++tp]=x;
}
void dfs3(rint u){
siz[u]=0;
for(rint i=h[u];i;i=e[i].nxt){
rint v=e[i].to;
dfs3(v);
siz[u]+=siz[v];
res+=1ll*siz[v]*(dis[v]-dis[u]-(v<=n))%p;
}
if(c[u]==col)siz[u]++;
else if(u<=n){
dp[0]=1;
for(rint i=1;i<=k;i++)
dp[i]=0;
for(rint i=h[u];i;i=e[i].nxt){
rint v=e[i].to;
for(rint j=k;j;j--)
dp[j]=(dp[j]+1ll*dp[j-1]*siz[v])%p;
}
for(rint i=1;i<=k;i++)
res+=dp[i];
}
h[u]=0;
}
void solve(){
tp=idx=0;
sort(g[col].begin(),g[col].end(),cmp);
if(g[col][0]!=1)stk[++tp]=1;
for(rint x:g[col])
insert(x);
while(tp>1)
Ins(stk[tp-1],stk[tp]),tp--;
dfs3(1);
}
int main(){
read(n);read(m);read(k);
for(rint i=1;i<=n;i++){
read(c[i]);
if(!mp[c[i]])mp[c[i]]=++colcnt;
c[i]=mp[c[i]];
}
while(m--){
rint a,b;
read(a);read(b);
g[a].push_back(b);g[b].push_back(a);
}
fang=n;
tarjan(1,0);
Time=0;
for(rint i=1;i<=n;i++)g[i].clear();
for(rint i=1;i<=n;i++)g[c[i]].push_back(i);
dfs1(1);
dfs2(1,1);
for(col=1;col<=colcnt;col++)
solve();
printf("%lld\n",res%p);
return 0;
}