8.13总结当日

今天我们队排名第四,然后总排排第6,勉强站住了区域赛的位置,还有12天,要继续加油啊


8.13场地址


B题:(Tarjan||暴力)

题意:

有一幅图,然后问你这幅图里面有多少个子图满足图的两个部分是完全对称的,而且这两个图要是完全图

解法:

由于large N*M最大为1e5,所以可以考虑直接暴力枚举每条边,之后从这两条边dfs下去,看它左右两边的子图是否对称

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<vector>
 5 using namespace std;
 6 const int maxn = 100 + 5;
 7 vector<int>g[maxn];
 8 int vis[maxn];
 9 int sz1, num1, sz2, num2;
10 
11 void dfs(int u,int v,int &sz,int &num) {
12     num += g[u].size(); sz += 1;
13     vis[u] = 1;
14     for (int k=0; k < g[u].size(); k++) {
15         if (vis[g[u][k]])continue;
16         if (g[u][k] == v)continue;
17         dfs(g[u][k], v, sz, num);
18     }
19 }
20 
21 int main() {
22     int T; scanf("%d", &T);
23     int kase = 0;
24     while (T--) {
25         int n, m; scanf("%d%d", &n, &m);
26         for (int i = 0; i <= n; i++)  g[i].clear(); 
27 
28         for (int i = 0; i < m; i++) {
29             int u, v; scanf("%d%d", &u, &v);
30             g[u].push_back(v);
31             g[v].push_back(u);
32         }
33 
34         int ans = 0;
35         for (int u = 1; u <= n; u++) {
36             for (int v = 0; v < g[u].size(); v++) {
37                 sz1 = sz2 = num1 = num2 = 0;
38 
39                 memset(vis, 0, sizeof(vis));
40                 dfs(u, g[u][v], sz1, num1);
41 
42                 memset(vis, 0, sizeof(vis));
43                 dfs(g[u][v], u, sz2, num2);
44 
45                 if (sz1 == sz2&&num1 == num2)
46                     if (num1 == sz1*(sz1 - 1) + 1)
47                         ans++;
48             }
49         }
50         printf("Case #%d: %d
", ++kase, ans/2);
51     }
52     return 0;
53 }

  


E题:(并查集)

题意:

有一个图,输出为n个数字,large n_{i} 表示第i个元素的父亲节点为large n_{i} ,接下来q次有两种询问,第一种是删除结点 i 和它的父节点,还有一种是问你两个节点是否连通

解法:

并查集解即可

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 int set[1000000];
 6 
 7 int findSet(int x) {
 8     if (x == set[x]) return x;
 9     int tmp= findSet(set[x]);
10     return tmp;
11 }
12 
13 void unionSet(int x, int y) {
14     int fx = findSet(x);
15     int fy = findSet(y);
16     if (fx != fy) {
17         set[fx] = fy;
18     }
19 }
20 
21 
22 int main() {
23     int T; scanf("%d", &T);
24     int kase = 1;
25     while (T--) {
26         memset(set, 0, sizeof(set));
27         int n, q; scanf("%d%d", &n, &q);
28         for (int i = 1; i <= n; i++) {
29             scanf("%d", &set[i]);
30             if (set[i] == 0)set[i] = i;
31         }
32 
33         printf("Case #%d:
", kase++);
34         for (int i = 0; i < q; i++) {
35             getchar(); char c; scanf("%c", &c);
36             if (c == 'C') {
37                 int f; scanf("%d", &f);
38                 set[f] = f;
39             }
40             else if (c == 'Q') {
41                 int a, b; scanf("%d%d", &a, &b);
42                 if (findSet(a) == findSet(b))printf("YES
");
43                 else printf("NO
");
44             }
45         }
46     }
47     return 0;
48 }

G: (不懂)

题意:

给你n盏灯,你有k个质数开关,每个质数开关可以控制是它的倍数的灯,每盏灯被打开奇数次才会亮,问如何控制开关使得亮的灯泡最多

解法:

对于<31的质数开关,直接暴力枚举所有状态,对于>=31的开关(任意两个>=31的质数开关不可能共同控制同一盏灯),就贪心一下,如果把它开起来能激活更多的灯,就开,否则就关。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<string>
 7 #include<cmath>
 8 #include<map>
 9 #include<set>
10 #include<vector>
11 #include<queue>
12 #include<string>
13 #include<bitset>
14 #include<ctime>
15 #include<deque>
16 #include<stack>
17 #include<functional>
18 #include<sstream>
19 typedef long long ll;
20 using namespace std;
21 typedef unsigned long long int ull;
22 #define maxn 200005
23 #define ms(x) memset(x,0,sizeof(x))
24 #define Inf 0x7fffffff
25 #define inf 0x3f3f3f3f
26 const int mod = 1e9 + 7;
27 #define pi acos(-1.0)
28 #define pii pair<int,int>
29 #define eps 1e-5
30 #define pll pair<ll,ll>
31 #define lson 2*x
32 #define rson 2*x+1
33 
34 int vis[maxn];
35 int t, n, k;
36 
37 void Find(int &res, int x) {
38     int i, j;
39     for (i = x; i <= n; i += x) {
40         if (vis[i] == 1)vis[i] = 0;
41         else vis[i] = 1;
42         if (vis[i])res++;
43         else res--;
44     }
45 }
46 
47 int main() {
48     scanf("%d", &t);
49     int cnt = 0;
50 
51     while (t--) {
52         cnt++;
53         int i, j;
54         vector<int>ve1, ve2;
55         scanf("%d%d", &n, &k);
56 
57         for (i = 1; i <= k; i++) {
58             int c; c = read();
59             if (c < 29)ve1.push_back(c);
60             else ve2.push_back(c);
61         }
62 
63         int maxx = 0;
64         for (i = 0; i < (1 << ve1.size()); i++) {
65             int res = 0;
66             ms(vis);
67 
68             for (j = 0; j < ve1.size(); j++) {
69                 if ((1 << j)&i) {
70                     Find(res, ve1[j]);
71                 }
72             }
73 
74             for (j = 0; j < ve2.size(); j++) {
75                 int tmp = 0;
76                 Find(tmp, ve2[j]);
77                 res += max(0, tmp);
78             }
79 
80             maxx = max(maxx, res);
81         }
82         //cout << maxx  << endl;
83         printf("Case #%d: %d
", cnt, maxx);
84     }
85 }

H题:(博弈dp)

题意:

有两支队,每只队都有n个人,一共有m个蛋糕,每个人至少吃一个,最多吃k个。

都采取最优策略,谁吃到最后一个蛋糕,那么那只队就胜利。

按照给定的顺序去吃蛋糕,问你最后谁胜利。

解法:

先缩点,把相同的点都缩成一个点。

那么就变成了ABABABA这样交替的形式了,然后跑DP就好了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const long long llINF = 9223372036854775807;
 4 const int INF = 2147483647;
 5 const int maxn = 1e3 + 7;
 6 const double pi = acos(-1.0);
 7 int t, n, m, k;
 8 char s[maxn << 1];
 9 int dp[maxn << 1][maxn << 1];
10 vector<int> v;
11 
12 int dfs(int now, int rest)
13 {
14     if (dp[now][rest] != -1)
15         return dp[now][rest];
16     if (rest <= v[now] * k)
17         return dp[now][rest] = 1;
18     dp[now][rest] = 0;
19     for (int i = v[now]; i <= k * v[now]; i++)
20         if (dfs(now + 1, rest - i) == 0)
21             return dp[now][rest] = 1;
22     return dp[now][rest];
23 }
24 
25 int main(int argc, char const *argv[])
26 {
27     scanf("%d", &t);
28     for (int kase = 1; kase <= t; kase++)
29     {
30         scanf("%d%d%d", &n, &m, &k);
31         n *= 2;
32         memset(dp, -1, sizeof(dp));
33         v.clear();
34 
35         scanf("%s", s + 1);
36 
37         for (int i = 1; i <= n; i++)
38         {
39             int j = i + 1;
40             while (j <= n && s[j] == s[i])
41                 j++;
42             v.push_back(j - i); //每次的人数
43             i = j - 1;
44         }
45 
46         printf("Case #%d: ", kase);
47         if (dfs(0, m))
48             puts(s[1] == 'A' ? "A" : "B");
49         else
50             puts(s[1] == 'A' ? "B" : "A");
51     }
52     return 0;
53 }
54  
原文地址:https://www.cnblogs.com/romaLzhih/p/9489791.html