• HDU 树型dp


    HDU 4123 Bob's Race

    题意:定义每个点的值为它到树上最远点的距离,每次询问q,回答最长的极值差小于等于q且编号连续的一段点的长度。
    题解:求距离两次dp,求极值ST表+尺取法。

    HDU 4514 湫湫系列故事——设计风景线

    题意:给一张图,如果有环,输出YES,否则为一个森林,求出每个树的直径,输出最大值。
    题解:并查集判环,两边dfs找直径。

    POJ 1655 Balancing Act

    题意:删掉一个点,使得分出的最大连通块大小最小
    题解:求重儿子,用重儿子大小和(n-sze[该子树])去更新答案。

    HDU 4714 Tree2cycle

    题意:删边或加边都有1的费用,求将一棵树变成一个环的最小费用。
    题解:贪心:将树拆成链再连成环。具体:对树进行dfs,如果一个节点有大于等于2个子节点,就删边保留两个子节点,并删除该节点与父亲的连边(特判根节点),最后答案为删边*2+1(连接图的首尾)。

    code

    hdu4123

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define maxn 50050
    #define maxm 550
    #define oo 0x3f3f3f3f
    int n, m;
    int ecnt, adj[maxn], go[maxn*2], len[maxn*2], nxt[maxn*2];
    int dp[maxn][5];  //0向下最大,1向下次大,2向上最大
    int delta[maxn], Log[25], ans;
    int mx[maxn][25], mn[maxn][25];
    
    inline void initLog() {
    	Log[0] = -1;
    	for(int i = 1; i <= 50005; i++) Log[i] = Log[i >> 1] + 1;
    }
    
    inline void addEdge(int u, int v, int c) {
    	nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v, len[ecnt] = c;
    }
    
    inline void init() {
    	for(int i = 1; i <= n; i++) adj[i] = 0;
    	ecnt = 0;
    	for(int i = 1; i <= n; i++) {
    		dp[i][0] = dp[i][1] = 0;
    		dp[i][2] = 0;
    	}
    }
    
    inline void dfs1(int u, int f) {
    	for(int e = adj[u]; e; e = nxt[e]) {
    		int v = go[e];
    		if(v == f) continue;
    		dfs1(v, u);
    		if(dp[v][0] + len[e] > dp[u][0]) {
    			dp[u][1] = dp[u][0];
    			dp[u][0] = dp[v][0] + len[e];
    		} else if(dp[v][0] + len[e] > dp[u][1]) {
    			dp[u][1] = dp[v][0] + len[e];
    		}
    	}
    }
    
    inline void dfs2(int u, int f) {
    	for(int e = adj[u]; e; e = nxt[e]) {
    		int v = go[e];
    		if(v == f) continue;
    		int t = ((dp[u][0] == dp[v][0] + len[e]) ? dp[u][1] : dp[u][0]);
    		dp[v][2] = max(t + len[e], dp[u][2] + len[e]);
    		dfs2(v, u);
    	}
    }
    
    inline int query(int l, int r){
    	int k = Log[r - l + 1];
    	int maxx = max(mx[l][k], mx[r - (1 << k) + 1][k]);
    	int minn = min(mn[l][k], mn[r - (1 << k) + 1][k]);
    	return maxx - minn;
    }
    
    int main() {
    	initLog();
    	while(scanf("%d%d", &n, &m) != EOF) {
    		if(!n && !m) return 0;
    		init();
    		for(int i = 1; i < n; i++) {
    			int x, y, z;
    			scanf("%d%d%d", &x, &y, &z);
    			addEdge(x, y, z);
    			addEdge(y, x, z);
    		}
    		dfs1(1, 0);
    		dfs2(1, 0);
    //		for(int i = 1; i <= n; i++) cout<<i<<" "<<dp[i][0]<<" "<<dp[i][1]<<" "<<dp[i][2]<<endl;
    		for(int i = 1; i <= n; i++) mx[i][0] = mn[i][0] = max(dp[i][0], dp[i][2]);
    		for(int j = 1; j <= Log[n]; j++)
    			for(int i = 1; i <= n; i++){
    				if(i + (1 << j) - 1 <= n){
    					mx[i][j] = max(mx[i][j - 1], mx[i + (1 << (j - 1))][j - 1]);
    					mn[i][j] = min(mn[i][j - 1], mn[i + (1 << (j - 1))][j - 1]);
    				}
    			}
    		for(int i = 1; i <= m; i++) {
    			int q, ans = 0;
    			scanf("%d", &q);
    			int head = 1;
    			for(int j = 1; j <= n; j++) {
    				while(head <= j && query(head, j) > q) head++;
    				ans = max(ans, j - head + 1);
    			}
    			printf("%d
    ",ans);
    		}
    	}
    }
    

    hdu4514

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int N = 100050, M = 1000050;
    int n, m;
    int ecnt, adj[N], go[M << 1], nxt[M << 1], len[M << 1];
    int vst[N], vt, anc[N], pos1, pos2, dis, ans;
    
    inline void addEdge(int u, int v, int l){
    	nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v, len[ecnt] = l;
    }
    
    inline void dfs(int u, int f, int l, int &pos){
    	vst[u] = vt;
    	if(l > dis){
    		pos = u;
    		dis = l;
    	}
    	for(int e = adj[u]; e; e = nxt[e]){
    		int v = go[e];
    		if(v == f) continue;
    		dfs(v, u, l + len[e], pos);
    	}
    }
    
    inline int getAnc(int x){
    	return x == anc[x] ? x :(anc[x] = getAnc(anc[x]));
    }
    
    int main(){
    	while(~scanf("%d%d", &n, &m)){
    		for(int i = 1; i <= n; i++) anc[i] = i, adj[i] = 0; ecnt = ans = 0;
    		bool flag = true;
    		for(int i = 1; i <= m; i++){
    			int x, y, z; scanf("%d%d%d", &x, &y, &z);
    			if(!flag) continue;
    			int fx = getAnc(x), fy = getAnc(y); 
    			if(fx == fy) flag = false;
    			if(flag) addEdge(x, y, z), addEdge(y, x, z), anc[fx] = fy;
    		}
    		if(!flag){
    			printf("YES
    ");
    			continue;
    		}
    		vt++;
    		for(int i = 1; i <= n; i++){
    			if(vst[i] == vt) continue;
    			dis = 0, pos1 = 0, pos2 = 0;
    			dfs(i, 0, 0, pos1);
    			dis = 0;
    			dfs(pos1, 0, 0, pos2);
    			ans = max(dis, ans);
    		}
    		printf("%d
    ", ans);
    	}
    }
    

    poj1655
    待填

    hdu4714

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    inline int read(){
    	int i = 0, f = 1; char ch = getchar();
    	for(; (ch < '0' || ch > '9') && ch != '-'; ch = getchar());
    	if(ch == '-') f = -1, ch = getchar();
    	for(; ch >= '0' && ch <= '9'; ch = getchar()) i = (i << 3) + (i << 1) + (ch - '0');
    	return i * f;
    }
    
    inline void wr(int x){
    	if(x < 0) putchar('-'), x = -x;
    	if(x > 9) wr(x / 10);
    	putchar(x % 10 + '0');
    }
    const int N = 1000050;
    int T, n;
    int ecnt, adj[N], go[N << 1], nxt[N << 1], cnt;
    
    inline void addEdge(int u, int v){
    	nxt[++ecnt] = adj[u], adj[u] = ecnt, go[ecnt] = v;
    }
    
    inline int dfs(int u, int f){
    	int ret = 0;
    	for(int e = adj[u]; e; e = nxt[e]){
    		int v = go[e];
    		if(v == f) continue;
    		ret += dfs(v, u);
    	}
    	if(ret >= 2){
    		cnt += ret - 2 + (u == 1 ? 0 : 1);
    		return 0;    //删去与父亲节点的边 
    	}
    	return 1;
    }
    
    int main(){
    	T = read();
    	while(T--){
    		n = read();
    		for(int i = 1; i <= n; i++) adj[i] = 0; ecnt = 0;
    		for(int i = 1; i < n; i++){
    			int x = read(), y = read();
    			addEdge(x, y);
    			addEdge(y, x);
    		}
    		cnt = 0;
    		dfs(1, 0);
    		wr(cnt * 2 + 1);
    		putchar('
    ');
    	}
    }
    
  • 相关阅读:
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp 8 Web基础
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp7 网络欺诈防范
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp6 MSF基础应用
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp5 信息搜集与漏洞扫描
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp4 恶意代码分析
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp3 免杀原理与实践
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp2 后门原理与实践
    # 2019-2020-2 网络对抗技术 20175333 曹雅坤 Exp1 PC平台逆向破解
    2019-2020-1 20175312 20175333 实验五 通讯协议设计
    2019-2020-2 20175320 《网络对抗技术》免考实践报告 手工实现对PE文件的shellcode注入
  • 原文地址:https://www.cnblogs.com/CzYoL/p/7726507.html
Copyright © 2020-2023  润新知