2021.3.7年度训练联盟热身训练赛第一场
F. Pulling Their Weight
题意:
输入n个数,分为两组,要求两组数的和相等,给定一个数t,要求t比一组的全部数大,比另一组的全部数小,找出最小的t。
tip:当t和n个数中的数有相同时,如果个数为偶数,就把他们分别分到两组,如果个数为奇数,就剔除一个,变成偶数,按偶数处理。
思路:
先排序,然后用前缀和记录对应区间的和。如果遍历到某个前缀和的2倍正好是所有数的和,那么这个前缀和对应的数+1(最小的t),就是想要的答案,
如果有两个相同元素,那就是这个前缀和对应的a值(因为偶数不会被踢)。还有当某个前缀和*2大于总和,就把这个数作为t。
#include <iostream> #include <cstring> #include <algorithm> #include <cmath> using namespace std; int n, a[100010], sum[100010], ans; int main() { memset(sum, 0, sizeof(sum)); cin >> n; for (int i = 1; i <= n; i++) cin >> a[i]; sort(a + 1, a + n + 1); for (int i = 1; i <= n; i++) sum[i] = sum[i - 1] + a[i]; for (int i = 1; i <= n; i++) { if (sum[i] * 2 > sum[n]) { ans = a[i]; break; } else if (sum[i] * 2 == sum[n]) { if (a[i] == a[i + 1]) { ans = a[i]; break; } else { ans = a[i] + 1; break; } } } cout << ans << endl; return 0; }
H.On Average They're Purple

题意:
无向图,你可以给边染色,如果走过的相邻两条边颜色不同,那么权值加一。求一种染色方案,起点终点所有路径中染色得到权值的最小值最大,输出权值。
由分析得所求颜色变化数为最短路径上步数减一
Dijkstra + heap:
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 6 using namespace std; 7 8 typedef pair<int , int>PII; 9 10 const int N = 1000010; 11 12 int n,m; 13 int h[N] , e[N] , ne[N] , w[N] , idx; 14 int dis[N]; 15 bool st[N]; 16 17 void add(int a , int b) 18 { 19 e[idx] = b , ne[idx] = h[a] , h[a] = idx ++ ; 20 } 21 22 int dijkstra() 23 { 24 memset(dis , 0x3f , sizeof dis); 25 dis[1] = 0; 26 27 priority_queue<PII , vector<PII> , greater<PII>> heap; 28 heap.push({0 , 1});//1号点距离为0 编号为1 29 30 while(!heap.empty()) 31 { 32 auto t = heap.top(); 33 heap.pop(); 34 35 int ver = t.second , distance = t.first; 36 if(st[ver]) continue;//ver这个点之前出现过了,是个冗余点 37 38 st[ver] = true; 39 40 for(int i = h[ver] ; i != -1 ; i = ne[i] ) 41 { 42 int j = e[i]; 43 if(dis[j] > distance + 1) 44 { 45 dis[j] = distance + 1; 46 heap.push({dis[j] , j}); 47 } 48 } 49 } 50 51 return dis[n]; 52 } 53 54 int main() 55 { 56 cin >> n >> m; 57 58 memset(h , -1 , sizeof h); 59 60 while(m -- ) 61 { 62 int a , b ; 63 cin >> a >> b; 64 add(a , b);//邻接表重边无所谓 65 add(b , a); 66 } 67 68 cout << dijkstra() - 1 << endl; 69 70 return 0; 71 }
Spfa:
1 #include <iostream> 2 #include <cstring> 3 #include <algorithm> 4 #include <queue> 5 6 using namespace std; 7 8 const int N = 1000010; 9 10 int n,m; 11 int h[N] , e[N] , ne[N] , idx; 12 int dis[N]; 13 bool st[N]; 14 15 void add(int a , int b) 16 { 17 e[idx] = b , ne[idx] = h[a] , h[a] = idx ++ ; 18 } 19 20 int spfa() 21 { 22 queue<int>q; 23 24 memset(dis , 0x3f , sizeof dis); 25 dis[1] = 0; 26 q.push(1); 27 st[1] = true;//判断当前点是否在队列当中 28 29 while(!q.empty()) 30 { 31 auto t = q.front(); 32 q.pop(); 33 st[t] = false;//这个点在队列中出来了,所以置为false 34 35 for(int i = h[t] ; i != -1 ; i = ne[i]) 36 { 37 int j = e[i]; 38 if(dis[j] > dis[t] + 1) 39 { 40 dis[j] = dis[t] + 1; 41 if(st[j] == false)//这个点不在队列当中才加到队列里 42 { 43 q.push(j); 44 st[j] = true; 45 } 46 } 47 } 48 } 49 50 return dis[n]; 51 } 52 53 int main() 54 { 55 cin >> n >> m; 56 57 memset(h , -1 , sizeof h); 58 59 while(m -- ) 60 { 61 int a , b; 62 cin >> a >> b; 63 add(a , b); 64 add(b , a); 65 } 66 67 int t = spfa(); 68 69 cout << t - 1 << endl; 70 71 return 0; 72 }

浙公网安备 33010602011771号