1. 程式人生 > >codeforces 796c Bank Hacking

codeforces 796c Bank Hacking

數量 直接 LG 枚舉 str 代碼 思維 最大值 multi

題意:

有很多家銀行,如果一個上線的銀行和另一個上線的銀行直接相連,那麽稱這種關系叫相鄰;

如果一個上線的銀行和另一個上線的銀行通過第三個上線銀行間接相連,稱這種情況為半相鄰。

每個銀行一開始是上線的並且有一個初始的防衛力量(可能為負數),一個銀行被搶劫之後就會下線並且再也不會上線,與它相鄰和半相鄰的所有上線的銀行防衛力量都加一。

一個人要去搶劫銀行,首先他會選擇一家銀行進行搶劫,之後搶劫的銀行需要滿足以下條件:

1.這家上線的銀行與一家下線的銀行直接相鄰;

2.這家銀行的防守值不能超過電腦的攻擊值。

問電腦的攻擊值最小為多少可以保證搶劫完所有的銀行。

思路:

首先理清題意,被搶劫的銀行必須與一家下線的銀行直接相鄰

。這個條件十分重要,它保證了每家銀行的防守值要麽加1,要麽加2。

所以,如果一家銀行的防守值為x,與它相連的所有銀行中的防守值最大為y,不與它相連的所有銀行中防守值最大的為z,那麽第一次搶劫這家銀行的答案就是x,y+1,z+2中的最大值。

所以第一種方法就出來啦,枚舉所有的銀行作為第一次的搶竊,然後算x,y,z。

這種方法稍不註意就會tle,但是巧妙的利用multiset就可以完美解決這個問題,復雜度為nlog(n),但是常數較大。

第二種方法就對思維的要求比較高。

設防守值的最大為mx,

那麽統計與每一個點直接相連的mx和mx-1的點的數量。

有一下三個情況:

1.只有一個mx,並且這個mx與所有的mx-1直接相鄰,這時答案就是mx;

2.一個mx與所有的mx直接相鄰,這時的答案是mx+1;

3.其他情況mx+2。

需要好好想一想。

方法1代碼:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <string>
 6 #include <vector>
 7 #include <set>
 8 using namespace std;
 9 
10 multiset<int> mmp;
11 const int inf = 0x3f3f3f3f; 12 const int N = 3e5 + 10; 13 int a[N]; 14 vector<int> g[N]; 15 16 int main() 17 { 18 int n; 19 20 scanf("%d",&n); 21 22 for (int i = 1;i <= n;i++) 23 { 24 scanf("%d",&a[i]); 25 mmp.insert(a[i]); 26 } 27 28 for (int i = 0;i < n - 1;i++) 29 { 30 int x,y; 31 scanf("%d%d",&x,&y); 32 g[x].push_back(y); 33 g[y].push_back(x); 34 } 35 36 int ans = inf; 37 38 for (int i = 1;i <= n;i++) 39 { 40 int tmp = a[i]; 41 mmp.erase(mmp.find(a[i])); 42 for (int j = 0;j < g[i].size();j++) 43 { 44 int k = a[g[i][j]]; 45 mmp.erase(mmp.find(k)); 46 tmp = max(k+1,tmp); 47 } 48 if (!mmp.empty()) tmp = max(tmp,*(--mmp.end()) + 2); 49 ans = min(tmp,ans); 50 mmp.insert(a[i]); 51 for (int j = 0;j < g[i].size();j++) 52 { 53 int k = a[g[i][j]]; 54 mmp.insert(k); 55 } 56 } 57 58 printf("%d\n",ans); 59 60 return 0; 61 }

方法2代碼:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 const int inf = 0x3f3f3f3f;
 7 const int N = 3e5 + 10;
 8 int a[N];
 9 vector<int> g[N];
10 
11 int main()
12 {
13     int n;
14     
15     scanf("%d",&n);
16     
17     int maxn = -inf;
18     
19     for (int i = 1;i <= n;i++)
20     {
21         scanf("%d",&a[i]);
22         maxn = max(maxn,a[i]);
23     }
24     
25     for (int i = 0;i < n - 1;i++)
26     {
27         int x,y;
28         scanf("%d%d",&x,&y);
29         g[x].push_back(y);
30         g[y].push_back(x);
31     }
32     
33     int mxd = 0,mx = 0;
34     
35     for (int i = 1;i <= n;i++)
36     {
37         if (a[i] == maxn) mx++;
38         if (a[i] == maxn - 1) mxd++;
39     }
40     
41     bool c = 0,d = 0,e = 0;
42     
43     if (mx == 1)
44     {
45         for (int i = 1;i <= n;i++)
46         {
47             if (a[i] == maxn)
48             {
49                 int cnt = 0;
50                 for (int j = 0;j < g[i].size();j++)
51                 {
52                     int x = a[g[i][j]];
53                     
54                     if (x == maxn - 1) cnt++;
55                 }
56                 if (cnt == mxd) c = 1;
57             }
58         }
59         
60         if (c) return 0*printf("%d",maxn);
61     }
62     
63     for (int i = 1;i <= n;i++)
64     {
65         int cnt = 0;
66         if (a[i] == maxn) cnt++;
67         for (int j = 0;j < g[i].size();j++)
68         {
69             if (a[g[i][j]] == maxn) cnt++;
70         }
71         if (cnt == mx) return 0*printf("%d",maxn + 1);
72     }
73     
74     printf("%d",maxn + 2);
75     
76     return 0;
77 }

codeforces 796c Bank Hacking