求从 n n n出发,每个点的所有支配点的编号和。
支配树。
在此只简述一下思路:
按 d f s dfs dfs序从大到小求出每个点的半支配点。
再通过半支配点求出支配点。
A C C o d e \mathcal AC \ Code AC Code
#include
#define maxn 50005
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
#define pb push_back
using namespace std;
int n,m;
vector<int>G[maxn],rG[maxn],Dm[maxn];
int dfn[maxn],mn[maxn],se[maxn],pos[maxn],F[maxn],idm[maxn],fa[maxn],tim;
int dep[maxn];
int Find(int u){
int t = F[u];
if(!t) return u;
int r = Find(F[u]);
if(dfn[se[mn[t]]] < dfn[se[mn[u]]]) mn[u] = mn[t];
return F[u] = r;
}
void dfs0(int u,int v=0){
pos[dfn[u] = ++tim] = u;
rep(i,0,G[u].size()-1){
v = G[u][i];if(dfn[v]) continue;
fa[v] = u;
dfs0(v,u);
}
}
void BuildDominatorTree(int rt = 1){
rep(i,1,n) se[i] = mn[i] = i , F[i] = dfn[i] = pos[i] = idm[i] = dep[i] = 0;
tim = 0;
dfs0(rt);
per(i,n,2){
int u = pos[i] , t = n;
rep(j,0,rG[u].size()-1){
int v = rG[u][j];if(!dfn[v]) continue;
if(dfn[v] < dfn[u]) t = min(t , dfn[v]);
else Find(v),t = min(t , dfn[se[mn[v]]]);
}
se[u] = pos[t] , F[u] = fa[u] , Dm[se[u]].pb(u);
u = pos[i-1];
rep(j,0,Dm[u].size()-1){
int v = Dm[u][j];Find(v);
if(se[mn[v]] == u) idm[v] = u;
else idm[v] = mn[v];
}
}
rep(i,2,n){
int u = pos[i];
if(idm[u] != se[u]) idm[u] = idm[idm[u]];
Dm[i].clear();
}
Dm[1].clear();
rep(i,1,n) if(idm[i]) Dm[idm[i]].pb(i);
}
void dfs1(int u,int v=0){
rep(i,0,Dm[u].size()-1){
v = Dm[u][i];
dep[v] = dep[u] + v;
dfs1(v);
}
}
int main(){
//freopen("1.in","r",stdin);
while(~scanf("%d%d",&n,&m)){
rep(i,1,m){
int u,v;
scanf("%d%d",&u,&v);
G[u].pb(v);
rG[v].pb(u);
}
BuildDominatorTree(n);
dep[n] = n;
dfs1(n);
rep(i,1,n) printf("%d%c",dep[i]," \n"[i==n]),G[i].clear(),rG[i].clear(),Dm[i].clear();
}
}
垃圾题目数据也太水了把,气得我连叉两个错解
对于 a i ∣ a j ∧ a i < a j a_i | a_j \wedge a_i < a_j ai∣aj∧ai<aj的连边 i → j i \rightarrow j i→j
求最长反链即可。
好像因为舞蹈链的某个剪枝的性质直接跑多重覆盖是对的。
离谱。
0 m s A C C o d e 0msAC \ Code 0msAC Code
#include
#define maxn 1005
#define LL long long
#define pb push_back
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;
int n;
vector<int>G[maxn];
LL a[maxn];
int vis[maxn],tim,cy[maxn],cx[maxn];
int dfs(int u){
rep(i,0,G[u].size()-1){
int v = G[u][i];
if(vis[v] == tim) continue;
vis[v] = tim;
if(!cy[v] || dfs(cy[v])){
cy[v] = u , cx[u] = v;
return 1;
}
}
return 0;
}
int main(){
int T;
for(scanf("%d",&T);T--;){
scanf("%d",&n);
int ans = 0;
rep(i,1,n) scanf("%lld",&a[i]) , G[i].clear() , cx[i] = cy[i] = 0;
sort(a+1,a+1+n);
n = unique(a+1,a+1+n) - a - 1;
rep(i,1,n) rep(j,i+1,n) if(a[j] % a[i] == 0)
G[i].pb(j);
rep(i,1,n) if(!cx[i]) ++tim , ans += dfs(i);
printf("%d\n",n - ans);
}
}