Codeforces Round #408 (Div. 2)C. Bank Hacking(STL)

题目链接:http://codeforces.com/problemset/problem/796/C

题目大意:有n家银行,第一次可以攻击任意一家银行(能量低于自身),跟被攻击银行相邻或者间接相邻(距离<=2)的银行能量+1,除了第一次外,攻击一家银行需要满足以下条件:

      ①:跟被攻击过后的银行相邻;

      ②:能量低于攻击者

      ③:银行没有被攻击过

题解:可以从题意得知,比如攻击银行i,如果说银行i能量为t,跟银行距离>=2的银行中能量最大的为mx,自身至少所需能量=max(t+1,mx+2),因为其他银行能量最多也只能+2;

   这样,我们只需要遍历1~n家银行找到最少需要的能量就可以了;

   这里我们用了两个c++数据结构,vector和multiset。vector属于<vector>是动态数组,multiset属于<set>会自动将里面的数字按从小到大排好;

   

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<set>
 4 #include<vector>
 5 using namespace std;
 6 const int N=3e5+5;
 7 vector<int>v[N];
 8 multiset<int>ms;
 9 
10 int main(){
11     int n,a,b;
12     int arr[N];
13     scanf("%d",&n);
14     for(int i=1;i<=n;i++){
15         scanf("%d",arr+i);
16         ms.insert(arr[i]);
17     }
18     for(int i=1;i<=n-1;i++){
19         scanf("%d %d",&a,&b);
20         v[a].push_back(b);
21         v[b].push_back(a);
22     }
23     int ans=1<<30;
24     multiset<int>::iterator it;
25     for(int i=1;i<=n;i++){//遍历n家银行,找到需要最少能量的银行 
26         //存下银行i的值后,在ms中删除 
27         int temp=arr[i];
28         ms.erase(ms.find(arr[i]));
29         //找到跟i相邻的银行,比较后,在ms中删除 
30         for(int j=0;j<v[i].size();j++){
31             int k=v[i][j];
32             temp=max(temp,arr[k]+1);
33             ms.erase(ms.find(arr[k]));
34         }
35         //比较距离大于2的银行能量最大值+2和temp的大小,保证每个银行都可以攻击 
36         if(!ms.empty()){
37             it=ms.end();
38             temp=max(temp,*(--it)+2);//由于ms.end()指向最后一位,而不是最后一个元素所以--it; 
39         }
40         //还原ms中删除的元素 
41         ms.insert(arr[i]);
42         for(int j=0;j<v[i].size();j++){
43             int k=v[i][j];
44             ms.insert(arr[k]);
45         }
46         ans=min(temp,ans);//找到所有情况中最少的能量 
47     }
48     printf("%d
",ans);
49 } 

 另外附上一种贪心写法:

C1为mx个数  C2为mx-1个数 
ans=mx 只有当C1=1&&正好有C2个mx-1与mx相连  
ans=mx+1 只有当存在一个点满足 其距离<=1内 mx的个数为C1 
其余情况ans=mx+2

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 typedef pair<ll,ll> ii;
 5 const ll inf=1e10;
 6 const int N=2e6+20;
 7 ll n,a[N],vis[N],can[N]; 
 8 vector<int> e[N];
 9 void solve()
10 {
11     ll C1=0,C2=0,mx=-inf,u;
12     for(int i=1;i<=n;i++)
13         mx=max(a[i],mx);
14     for(int i=1;i<=n;i++)
15     {
16         if(a[i]==mx)
17             C1++,u=i;
18         else if(a[i]==mx-1)
19             C2++; 
20     }
21     ll ans=inf;
22     if(C1==1)//
23     {
24         int cnt=0;
25         for(int i=0;i<e[u].size();i++)
26         {
27             int v=e[u][i];
28             if(a[v]==mx-1)
29                 cnt++;
30         }
31         if(cnt==C2)
32             ans=mx;
33     }
34     if(ans==inf)
35     {
36         for(int i=1;i<=n&&ans==inf;i++)//遍历边O(n),找到相邻为1内,有C1个mx  
37         {
38             ll res=0;
39             if(a[i]==mx)
40                 res++;
41             for(int j=0;j<e[i].size();j++)
42             {
43                 int v=e[i][j];
44                 if(a[v]==mx)
45                     res++;
46             }
47             if(res==C1)
48                 ans=mx+1;
49         }
50     }
51     if(ans==inf)
52         ans=mx+2;
53     cout<<ans<<endl;
54 }
55 int main()
56 {
57     while(cin>>n)
58     {
59         for(int i=1;i<=n;i++)
60             scanf("%I64d",&a[i]),e[i].clear();
61         int u,v;
62         for(int i=1;i<=n-1;i++)
63         {
64             scanf("%d%d",&u,&v);
65             e[u].push_back(v);
66             e[v].push_back(u);
67         }
68         solve();
69     }
70     return 0;
71 }
原文地址:https://www.cnblogs.com/fu3638/p/6696994.html