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 }

 

posted @ 2021-03-12 10:18  彦辰kkkkk  阅读(73)  评论(0)    收藏  举报