# 「ZR 18 省选 3」题解

## A. 树的染色

#include <bits/stdc++.h>

#define fi first
#define se second
#define db double
#define U unsigned
#define P std::pair<int,int>
#define LL long long
#define pb push_back
#define MP std::make_pair
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 1000+5;
const int MAXM = 5000+5;

std::vector<int> G[MAXN];
int n,a[MAXN];
int f[MAXN];
// 和 v 颜色不同的最小代价 (钦定 v 颜色为 0)
int g[2][MAXM];
bool flag;

inline void dfs(int v){
if(G[v].empty()){
f[v] = 0;
return;
}
for(auto x:G[v]) dfs(x);
int now = 0;CLR(g[now],0x3f);g[now][0] = 0;
for(auto x:G[v]){
CLR(g[now^1],0x3f);
FOR(i,0,MAXM){
if(i+a[x] < MAXM) g[now^1][i+a[x]] = std::min(g[now^1][i+a[x]],g[now][i]+f[x]);
if(i+f[x] < MAXM) g[now^1][i+f[x]] = std::min(g[now^1][i+f[x]],g[now][i]+a[x]);
}
now ^= 1;
}
f[v] = 0x3f3f3f3f;
FOR(i,0,a[v]) f[v] = std::min(f[v],g[now][i]);
if(f[v] == 0x3f3f3f3f) flag = 0;
}

inline void Solve(){
scanf("%d",&n);FOR(i,1,n) G[i].clear();
FOR(i,2,n){
int f;scanf("%d",&f);G[f].pb(i);
}
FOR(i,1,n) scanf("%d",a+i);
flag = 1;dfs(1);
puts(flag?"POSSIBLE":"IMPOSSIBLE");
}

int main(){
int T;scanf("%d",&T);
while(T--) Solve();
return 0;
}



## B. 树形图求和

### 做法 1：伴随矩阵

$\forall i ,|A| = \sum_{j=1}^n C_{i,j}A_{i,j}$

### 做法 2：多项式

#include <bits/stdc++.h>

#define fi first
#define se second
#define db double
#define U unsigned
#define P std::pair<int,int>
#define LL long long
#define pb push_back
#define MP std::make_pair
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 300+5;
const int ha = 1e9 + 7;

inline int qpow(int a,int n=ha-2){
int res = 1;
while(n){
if(n & 1) res = 1ll*res*a%ha;
a = 1ll*a*a%ha;
n >>= 1;
}
return res;
}

int a[MAXN][MAXN],n,m;
int A[MAXN][MAXN],b[MAXN][MAXN];
// b: 伴随矩阵
// A: 原矩阵
// a: 消元用

struct Edge{
int u,v,w;
Edge(int u=0,int v=0,int w=0) : u(u),v(v),w(w) {}
}e[200000+5];

x += y-ha;x += x>>31&ha;
}

inline int Gauss(){
FOR(i,1,n) b[i][i] = 1;
int ans = 1;
FOR(i,1,n){
int t = -1;
FOR(j,i,n) if(a[j][i]){t = j;break;}
if(t != i) std::swap(a[i],a[t]),ans = ha-ans,std::swap(b[i],b[t]);
ans = 1ll*ans*a[i][i]%ha;
int inv = qpow(a[i][i]);
FOR(j,1,n) a[i][j] = 1ll*a[i][j]*inv%ha,b[i][j] = 1ll*b[i][j]*inv%ha;
FOR(j,1,n){
if(j == i) continue;
int t = a[j][i];
FOR(k,1,n){
}
}
}
FOR(i,1,n) FOR(j,1,n) b[i][j] = 1ll*b[i][j]*ans%ha;
return ans;
}

int main(){
scanf("%d%d",&n,&m);
FOR(i,1,m){
int u,v,w;scanf("%d%d%d",&u,&v,&w);e[i] = Edge(u,v,w);
}
FOR(i,1,n) a[n][i] = a[i][n] = 0;
--n;
FOR(i,1,n) FOR(j,1,n) A[i][j] = a[i][j];
Gauss();
int ans = 0;
FOR(i,1,m){
int u = e[i].u,v = e[i].v,w = e[i].w;
if(u == n+1) continue;
int c = (b[u][u]+ha-b[v][u])%ha;
/*
if(v != n+1){
}
}
printf("%d\n",ans);
return 0;
}



## C. 波波老师

#include <bits/stdc++.h>

#define fi first
#define se second
#define db double
#define U unsigned
#define P std::pair<int,int>
#define LL long long
#define pb push_back
#define MP std::make_pair
#define all(x) x.begin(),x.end()
#define CLR(i,a) memset(i,a,sizeof(i))
#define FOR(i,a,b) for(int i = a;i <= b;++i)
#define ROF(i,a,b) for(int i = a;i >= b;--i)
#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

const int MAXN = 5e6 + 5;

int ch[MAXN<<1][5],fail[MAXN<<1],len[MAXN<<1],tot = 1,las = 1;
int id[MAXN];
char str[MAXN];
bool vis[MAXN<<1];
int n;

inline int insert(int c){
int p = las,np = las = ++tot;len[np] = len[p]+1;
for(;p&&!ch[p][c];p=fail[p]) ch[p][c] = np;
if(!p) fail[np] = 1;
else{
int q = ch[p][c];
if(len[q] == len[p]+1) fail[np] = q;
else{
int nq = ++tot;FOR(i,0,4) ch[nq][i] = ch[q][i];len[nq] = len[p]+1;fail[nq] = fail[q];
fail[q] = fail[np] = nq;
for(;p&&ch[p][c]==q;p=fail[p]) ch[p][c] = nq;
}
}
return np;
}

int ans[MAXN];
int f[MAXN];

int main(){
scanf("%s",str+1);n = strlen(str+1);
ROF(i,n,1) id[i] = insert(str[i]-'a');
FOR(i,1,tot) vis[fail[i]] = 1;
FOR(i,1,n){
if(vis[id[i]]) f[i] = 1e9;
else f[i] = len[fail[id[i]]]+1;
//        DEBUG(f[i]);
}
std::deque<int> q;
FOR(i,1,n) ans[i] = 1e9;
FOR(i,1,n){
while(!q.empty() && f[q.back()] >= f[i]) q.pop_back();
q.pb(i);
ans[i] = f[q[0]];
while(!q.empty() && q[0]+f[q[0]]-1 <= i) q.pop_front();
}
FOR(i,2,n) ans[i] = std::min(ans[i],ans[i-1]+1);
LL res = 0;FOR(i,1,n) res += ans[i];
printf("%lld\n",res);
return 0;
}

posted @ 2020-12-06 21:53  RainAir  阅读(25)  评论(0编辑  收藏