仙人掌、圆方树、支配树、舞蹈链作业(下)

HDU 4694 Important Sisters

求从 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();
	}
}

HDU 3335 Divisibility

垃圾题目数据也太水了把,气得我连叉两个错解
对于 a i ∣ a j ∧ a i < a j a_i | a_j \wedge a_i < a_j aiajai<aj的连边 i → j i \rightarrow j ij
求最长反链即可。
好像因为舞蹈链的某个剪枝的性质直接跑多重覆盖是对的。
离谱。

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);
	}
}

你可能感兴趣的:(仙人掌、圆方树、支配树、舞蹈链作业(下))