由于天梯赛不能带模板,对于我这种模板严重依赖患者是很难受的,又因为去年打那么菜,今年题目不是太难的话怎么着也得上200呀,所以来重新打一遍模板,交一下裸题验证其正确性。
需要准备的也不是太多,主要是一些基本的图论算法以及dp。毕竟都是理解了的,应该不会耗时很久。
就按照白书上面的顺序来敲吧。
一、01背包
二维的:
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问题
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;
}