天梯赛的一点小准备

由于天梯赛不能带模板,对于我这种模板严重依赖患者是很难受的,又因为去年打那么菜,今年题目不是太难的话怎么着也得上200呀,所以来重新打一遍模板,交一下裸题验证其正确性。

需要准备的也不是太多,主要是一些基本的图论算法以及dp。毕竟都是理解了的,应该不会耗时很久。

就按照白书上面的顺序来敲吧。

 

一、01背包

题目:Bone Collector

二维的:

int dp[maxn][maxn];
int w[maxn], v[maxn];

int main()
{
	int t; scanf("%d", &t);
	while(t--){
		memset(dp, 0, sizeof(dp));
		int n, V; scanf("%d %d", &n, &V);
		rep(i, 1, n) scanf("%d", v + i);
		rep(i, 1, n) scanf("%d", w + i);
		rep(i, 1, n){
			rep(j, 0, V){
				if(w[i] > j) dp[i][j] = dp[i-1][j];
				else dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]] + v[i]);
			}
		}
		printf("%d\n", dp[n][V]);
	}
	return 0;
}

一维的:

int dp[maxn];
int w[maxn], v[maxn];

int main()
{
	int t; scanf("%d", &t);
	while(t--){
		memset(dp, 0, sizeof(dp));
		int n, V; scanf("%d %d", &n, &V);
		rep(i, 1, n) scanf("%d", v + i);
		rep(i, 1, n) scanf("%d", w + i);
		rep(i, 1, n){
			Rep(j, V, w[i]){
				dp[j] = max(dp[j], dp[j-w[i]] + v[i]);
			}
		}
		printf("%d\n", dp[V]);
	}
	return 0;
}

 

二、LCS问题

题目:Common Subsequence

char s[maxn], t[maxn];
int dp[maxn][maxn];

int main()
{
	while(~scanf(" %s %s", s + 1, t + 1)){
		memset(dp, 0, sizeof(dp));
		int n = strlen(s + 1), m = strlen(t + 1);
		rep(i, 1, n){
			rep(j, 1, m){
				if(s[i] == t[j]) dp[i][j] = dp[i-1][j-1] + 1;
				else dp[i][j] = max(dp[i-1][j], dp[i][j-1]);
			}
		}
		printf("%d\n", dp[n][m]);
	}
	return 0;
}

 

三、完全背包问题

题目:Piggy-Bank

直接一维吧:

int w[505], v[505];
int dp[10005];

int main()
{
	int t; scanf("%d", &t);
	while(t--){
		int e, f; scanf("%d %d", &e, &f);
		int V = f - e;
		rep(i, 0, V) dp[i] = inf;
		int n; scanf("%d", &n);
		rep(i, 1, n) scanf("%d %d", v + i, w + i);
		dp[0] = 0;
		rep(i, 1, n){
			rep(j, w[i], V){
				dp[j] = min(dp[j], dp[j-w[i]] + v[i]);
			}
		}
		if(dp[V] == inf) puts("This is impossible.");
		else printf("The minimum amount of money in the piggy-bank is %d.\n", dp[V]);
	}
	return 0;
}

四、多重部分和问题

题目:Dividing

int a[10] = {0, 1, 2, 3, 4, 5, 6 }, m[10];
int dp[maxn];

int main()
{
	int cnt = 0;
	while(~scanf("%d", m + 1)){
		rep(i, 2, 6) scanf("%d", m + i);
		bool f = 0;
		rep(i, 1, 6) if(m[i]) f = 1;
		if(!f) break;
		printf("Collection #%d:\n", ++cnt);
		int sum = 0;
		rep(i, 1, 6){
			sum += i * m[i];
		}
		if(sum & 1) { puts("Can't be divided.\n"); continue; }
		sum /= 2;
		fill(dp, dp + sum + 1, -1);
		dp[0] = 0;
		rep(i, 1, 6){
			rep(j, 0, sum){
				if(dp[j] >= 0) dp[j] = m[i];
				else if(j < a[i] || dp[j-a[i]] <= 0){
					dp[j] = -1;
				}
				else dp[j] = dp[j-a[i]] - 1;
			}
		}
		if(dp[sum] >= 0) puts("Can be divided.");
		else puts("Can't be divided.");
		puts("");
	}
	return 0;
}

五、LIS问题

题目:Longest Ordered Subsequence

int a[maxn];
int dp[maxn];

int main()
{
	int n; scanf("%d", &n);
	rep(i, 1, n) scanf("%d", a + i);
	fill(dp, dp + n + 1, inf);
	rep(i, 1, n){
		*lower_bound(dp + 1, dp + n + 1, a[i]) = a[i];
	}
	printf("%d\n", lower_bound(dp + 1, dp + n + 1, inf) - dp - 1);
	return 0;
}

六、优先队列的定义&重载

struct node{
	int x, y, t;
	friend bool operator < (node a, node b){
		return a.t > b.t;
	}
};

priority_queue<node> q;

七、并查集

题目:The Suspects

int fa[maxn];
int n, m;

int Find(int x){
	return x == fa[x] ? x : fa[x] = Find(fa[x]);
}

void uni(int x, int y){
	fa[Find(x)] = Find(y);
}

void init(){
	rep(i, 0, n) fa[i] = i;
}

int main()
{
	while(~scanf("%d %d", &n, &m) && !(!n && !m)){
		init();
		rep(i, 1, m){
			int num; scanf("%d", &num);
			int x; scanf("%d", &x);
			rep(j, 1, num - 1){
				int y; scanf("%d", &y);
				uni(x, y);
			}
		}
		int fa0 = Find(0);
		int cnt = 1;
		rep(i, 1, n - 1){
			if(Find(i) == fa0) cnt++;
		}
		printf("%d\n", cnt);
	}
	return 0;
}

 

八、最短路问题

floyd:

问题:Cow Contest (求有向图传递闭包)

bool vis[maxn][maxn];

int main()
{
	int n, m; scanf("%d %d", &n, &m);
	rep(i, 1, n) vis[i][i] = 1;
	rep(i, 1, m){
		int u, v; scanf("%d %d", &u, &v);
		vis[u][v] = 1;
	}
	rep(k, 1, n){
		rep(i, 1, n){
			rep(j, 1, n){
				vis[i][j] |= (vis[i][k] && vis[k][j]);
			}
		}
	}
	int cnt = 0;
	rep(i, 1, n){
		bool f = 1;
		rep(j, 1, n){
			if(!vis[i][j] && !vis[j][i]) f = 0;
		}
		if(f) cnt++;
	}
	printf("%d\n", cnt);
	return 0;
}

Bellman_Ford:

题目:Wormholes

struct edge{
	int from, to, cost;
}e[maxn];

int d[maxn];
int n, m, m2;

bool Bellman_Frod(int s){
	memset(d, 0, sizeof(d));
	rep(i, 1, n){
		rep(j, 1, 2 * m + m2){
			edge t = e[j];
			if(d[t.to] > d[t.from] + t.cost){
				d[t.to] = d[t.from] + t.cost;
				if(i == n) return true;
			}
		}
	}
	return false;
}

int main()
{
	int t; scanf("%d", &t);
	while(t--){
		scanf("%d %d %d", &n, &m, &m2);
		rep(i, 1, m){
			scanf("%d %d %d", &e[i].from, &e[i].to, &e[i].cost);
			e[i+m].from = e[i].to, e[i+m].to = e[i].from, e[i+m].cost = e[i].cost;
		}
		rep(i, 2 * m + 1, 2 * m + m2){
			scanf("%d %d %d", &e[i].from, &e[i].to, &e[i].cost);
			e[i].cost = -e[i].cost;
		}
		puts(Bellman_Frod(1) ? "YES" : "NO");
	}
	return 0;
}

dijkstra:

题目:畅通工程续

朴素版:

vector<PII> G[maxn];
bool vis[maxn];
int d[maxn];
int n, m;

void dij(int s){
	fill(d, d + n + 1, inf);
	fill(vis, vis + n + 1, 0);
	d[s] = 0;
	while(1){
		int v = -1;
		rep(u, 0, n - 1) {
			if(!vis[u] && (v == -1 || d[v] > d[u])) v = u;
		}
		if(v == -1) break;
		vis[v] = 1;
		int len = G[v].size();
		rep(i, 0, len - 1){
			int u = G[v][i].fi;
			if(vis[u]) continue;
			d[u] = min(d[u], d[v] + G[v][i].se);
		}
	}
}

int main()
{
	while(~scanf("%d %d", &n, &m)){
		rep(i, 0, n - 1) G[i].clear();
		rep(i, 1, m){
			int u, v, w; scanf("%d %d %d", &u, &v, &w);
			G[u].pb(mp(v, w));
			G[v].pb(mp(u, w));
		}
		int s, t; scanf("%d %d", &s, &t);
		dij(s);
		printf("%d\n", d[t] == inf ? -1 : d[t]);
	}
	return 0;
}

堆优化:

struct edge{
	int to, cost;
	edge(){}
	edge(int to, int cost){
		this->to = to, this->cost = cost;
	}
};

vector<edge> G[maxn];
int d[maxn];
int n, m;

void dij(int s){
	priority_queue<PII, vector<PII>, greater<PII> > q;
	fill(d, d + n + 1, inf);
	d[s] = 0;
	q.push(PII(0, s));
	while(!q.empty()){
		PII p = q.top(); q.pop();
		int v = p.se;
		if(d[v] < p.fi) continue;
		int len = G[v].size();
		rep(i, 0, len - 1){
			edge e = G[v][i];
			if(d[e.to] > d[v] + e.cost){
				d[e.to] = d[v] + e.cost;
				q.push(PII(d[e.to], e.to));
			}
		}
	}
}

int main()
{
	while(~scanf("%d %d", &n, &m)){
		rep(i, 0, n - 1) G[i].clear();
		rep(i, 1, m){
			int u, v, w; scanf("%d %d %d", &u, &v, &w);
			G[u].pb(edge(v, w));
			G[v].pb(edge(u, w));
		}
		int s, t; scanf("%d %d", &s, &t);
		dij(s);
		printf("%d\n", d[t] == inf ? -1 : d[t]);
	}
	return 0;
}

九、MST

题目:Networking

Kruskal:

struct edge{
	int u, v, cost;
	friend bool operator < (edge a, edge b){
		return a.cost < b.cost;
	}
};

edge es[maxm];
int fa[maxn];
int n, m;

int Find(int x){ return fa[x] == x ? x : fa[x] = Find(fa[x]); }
void uni(int x, int y){ fa[Find(x)] = Find(y); }
void init(){ rep(i, 0, n + 1) fa[i] = i; }

int solve(){
	init();
	sort(es + 1, es + m + 1);
	int res = 0;
	rep(i, 1, m){
		edge e = es[i];
		if(Find(e.u) != Find(e.v)){
			uni(e.u, e.v);
			res += e.cost;
		}
	}
	return res;
}

int main()
{
	while(~scanf("%d", &n) && n){
		scanf("%d", &m);
		rep(i, 1, m){
			scanf("%d %d %d", &es[i].u, &es[i].v, &es[i].cost);
		}
		printf("%d\n", solve());
	}
	return 0;
}

 

  • 8
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值