zoukankan      html  css  js  c++  java
  • 2019 Wannafly summer camp Day1

    赛后补题:

      A:(https://codeforces.com/contest/449/problem/B

      最短路+思维

      对不起,我不会写Dijkstra

      不知道从什么时候开始,我的Dij一直是这样的:

      

    1 struct cmp{
    2     bool operator()(int a,int b){
    3         return dis[a]>dis[b];
    4     }
    5 };
    6 priority_queue<int,vector<int>,cmp>pq;

      正确写法:

     

    struct cmp {
        bool operator()(pil a, pil b) {
            return a.second > b.second;
        };
    };
    
    priority_queue<pil, vector<pil >, cmp> pq;

    很明显这是错的。。。hhhhh

    原因在于:这个堆因为dis[u]会变化,所以这个堆根本就是个假的堆!

    从另一个角度来讲:

    队列中维护的是入队时候的dis而不是时时变化的dis,dis会随着更新而变化

    还有一个地方:

     1  void dij() {
     2         fill(dis, dis + maxn, 1e18);
     3         priority_queue<pil, vector<pil >, cmp> pq;
     4         pq.push({1, 0});
     5         dis[1] = 0;
     6         while (!pq.empty()) {
     7             int now = pq.top().first;
     8             pq.pop();
     9             if (vis[now]) continue;                              //一定要有入队标记,否则重复入队会T到飞起
    10             vis[now] = 1;
    11             for (int i = 0; i < G[now].size(); ++i) {
    12                 int to = G[now][i].first,
    13                         v = G[now][i].second;
    14  
    15                 if (!vis[to] && dis[to] > dis[now] + v) {        //这里更新的时候也要看是否已经入队
    16                     ind[to] = 1;
    17                     dis[to] = dis[now] + v;
    18                     pq.push({to, dis[to]});
    19                 } //else if (dis[to] == dis[now] + v) ++ind[to]; //这是根据本题题意来的。
    20             }
    21         }
    22     }

     综上所述:我不会写dij,,,,hhhhh(天知道我之前的最短路都是怎么过的)

      下面贴完整代码:

     

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 #define pil pair<int,ll>
     4 using namespace std;
     5  
     6 const int maxn=1e5+5;
     7 bool vis[maxn];
     8 int n,m,k,ind[maxn];
     9 ll dis[maxn],minn[maxn];
    10 vector<pil>G[maxn];
    11  
    12  
    13 struct cmp {
    14     bool operator()(pil a, pil b) {
    15         return a.second > b.second;
    16     };
    17 };
    18  
    19  
    20     void dij() {
    21         fill(dis, dis + maxn, 1e18);
    22         priority_queue<pil, vector<pil >, cmp> pq;
    23         pq.push({1, 0});
    24         dis[1] = 0;
    25         while (!pq.empty()) {
    26             int now = pq.top().first;
    27             pq.pop();
    28             if (vis[now]) continue;
    29             vis[now] = 1;
    30             for (int i = 0; i < G[now].size(); ++i) {
    31                 int to = G[now][i].first,
    32                         v = G[now][i].second;
    33  
    34                 if (!vis[to] && dis[to] > dis[now] + v) {
    35                     ind[to] = 1;
    36                     dis[to] = dis[now] + v;
    37                     pq.push({to, dis[to]});
    38                 } else if (dis[to] == dis[now] + v) ++ind[to];
    39             }
    40         }
    41     }
    42  
    43     int main() {
    44         ios::sync_with_stdio(0);
    45         cin >> n >> m >> k;
    46         for (int i = 1; i <= m; ++i) {
    47             int a, b, c;
    48             cin >> a >> b >> c;
    49             G[a].push_back({b, c});
    50             G[b].push_back({a, c});
    51         }
    52         int ans = 0;
    53         for (int i = 1; i <= k; ++i) {
    54             int a;
    55             ll b;
    56             cin >> a >> b;
    57             if (minn[a]) {
    58                 ++ans;
    59                 minn[a] = min(minn[a], b);
    60             } else minn[a] = b;
    61         }
    62         for (int i = 2; i <= n; ++i) {
    63             if (minn[i]) {
    64                 G[1].push_back({i, minn[i]});
    65                 G[i].push_back({1, minn[i]});
    66             }
    67         }
    68         dij();
    69         for (int i = 2; i <= n; ++i) {
    70             if (minn[i]) {
    71                 if (minn[i] > dis[i]) {
    72                     ++ans;
    73                 }
    74                 if (minn[i] == dis[i] && ind[i] > 1)++ans;
    75             }
    76         }
    77         cout << ans << endl;
    78     }

    还要注意的是:最短路图的入度是在Dij的过程中确定的,更新一次后(dis[to]>dis[now]+v),to的入度变为1,如果(dis[to]==dis[now]+v),to的入度+1

            确定入度和最短路计数也不太一样,计数时,更新一次后(dis[to]>dis[now]+v),to的入度变为indegree[now],如果(dis[to]==dis[now]+v),indegree[to]+indegree[now]

    B - Phillip and Trains

      BFS/DFS水题,注意一下人的运动要先前进一格在上下移动,不可以先上下移动再前进一格,开始没读好题

      

     1 #include<bits/stdc++.h>
     2 #define pii pair<int,int>
     3 using namespace std;
     4 int start;
     5  
     6 const int maxn=1e3+5;
     7 char plat[5][maxn];
     8 bool vis[5][maxn];
     9 int n;
    10 int all_f;
    11 bool move(int x,int y)
    12 {
    13     return plat[x][y+1]=='.' && plat[x][y+2]=='.';
    14 }
    15 bool bfs()
    16 {
    17     queue<pii>q;
    18     q.push({start,1});
    19     while(!q.empty())
    20     {
    21         pii now=q.front();
    22         q.pop();
    23         int x=now.first,y=now.second;
    24         if(y>=n) return 1;
    25         if(vis[x][y]) continue;
    26         vis[x][y]=1;
    27         if(plat[x][y+1]!='.') continue;
    28         for(int i=-1;i<=1;++i)
    29         {
    30             if(plat[x+i][y+1]=='.' && move(x+i,y+1))
    31             {
    32                 q.push({x+i,y+3});
    33             }
    34         }
    35     }
    36     return 0;
    37 }
    38 int main()
    39 {
    40     int t;
    41     ios::sync_with_stdio(0);
    42     cin>>t;
    43     while(t--)
    44     {
    45         all_f=0;
    46         memset(plat,0,sizeof(plat));
    47         memset(vis,0,sizeof(vis));int no;
    48         cin>>n>>no;
    49         cin>>plat[1]+1>>plat[2]+1>>plat[3]+1;
    50         for(int i=1;i<=3;++i)
    51         {
    52             for(int j=1;j<=n;++j)
    53             {
    54                 if(plat[i][j]=='s') start=i;
    55                 plat[i][j+n]='.';
    56             }
    57         }
    58         cout<<(bfs()?"YES":"NO")<<endl;
    59     }
    60 }

    C - A Mist of Florescence

      给4个数abcd表示ABCD四个字母连通块的个数,构造一个矩阵使其ABCD连通块的个数为abcd

      构造+思维,

      排序以下,由小到大分别为ABCD,ABC各拿出来一个,先ABABAB排,用C个开一层,再用B隔开一层,再CDCDCD排,A隔开然后BDBDBD排,最后剩下的B/D嵌到A中。

      

      1 #include<bits/stdc++.h>
      2 #define pii pair<int,int>
      3 using namespace std;
      4 int a,b,c,d;
      5 int ans[51][51];
      6 pii blo[10];
      7 int main()
      8 {
      9     for(int i=1;i<=4;++i) cin>>blo[i].first,blo[i].second=i;
     10     sort(blo+1,blo+1+4);
     11     a=blo[1].first,b=blo[2].first,c=blo[3].first,d=blo[4].first;
     12     --a,--b,--c;
     13     int minn=a;
     14     int col=1,row=1;
     15     b-=a;
     16     while(a)
     17     {
     18         if(row&1)
     19         {
     20             ans[row][col++]=1;
     21             ans[row][col++]=2;
     22         }
     23         else
     24         {
     25             ans[row][col++]=2;
     26             ans[row][col++]=1;
     27         }
     28         --a;
     29         if(col==51)
     30         {
     31             col=1;
     32             ++row;
     33         }
     34     }
     35     for(int i=col;i<=50;++i) ans[row][i]=3;
     36     for(int i=1;i<=50;++i) ans[row+1][i]=3;
     37     for(int i=1;i<=50;++i) ans[row+2][i]=2;
     38     minn=c;
     39     row+=3,col=1;
     40     d-=c;
     41     while(c)
     42     {
     43         if(row&1)
     44         {
     45             ans[row][col++]=3;
     46             ans[row][col++]=4;
     47         }
     48         else
     49         {
     50             ans[row][col++]=4;
     51             ans[row][col++]=3;
     52         }
     53         --c;
     54         if(col==51)
     55         {
     56             col=1;
     57             ++row;
     58         }
     59     }
     60     
     61     for(int i=col;i<=50;++i) ans[row][i]=1;
     62     for(int i=1;i<=50;++i) ans[row+1][i]=1;
     63     row+=2;col=1;
     64     minn=min(b,d);
     65     int bb=b,dd=d;
     66     while(minn)
     67     {
     68         //cout<<"Q"<<endl;
     69         if(row&1)
     70         {
     71             ans[row][col++]=2;
     72             ans[row][col++]=4;
     73         }
     74         else
     75         {
     76             ans[row][col++]=4;
     77             ans[row][col++]=2;
     78         }
     79         --minn;
     80         if(col==49)
     81         {
     82             col=1;
     83             ans[row][49]=1;
     84             ans[row][50]=1;
     85             ++row;
     86         }
     87     }
     88     for(int i=col;i<=50;++i) ans[row][i]=1;
     89     ++row;
     90     for(int i=1;i<=50;++i) ans[row][i]=1;
     91     ++row;
     92     int red=abs(b-d);
     93     col=1;
     94     while(red)
     95     {
     96         --red;
     97         ans[row][col++]=7;
     98         ans[row][col++]=1;
     99         if(col==51) 
    100         {
    101             col=1,++row;
    102             for(int i=1;i<=50;++i) ans[row][i]=1;
    103             ++row;
    104         }
    105     }
    106     for(int i=col;i<=50;++i) ans[row][i]=1;
    107     int p=bb>dd?2:4;
    108     for(int i=1;i<=50;++i)
    109     {
    110         for(int j=1;j<=50;++j)
    111         {
    112             if(ans[i][j]==7) ans[i][j]=p;
    113         }
    114     }
    115     cout<<row<<" "<<50<<endl;
    116     for(int i=1;i<=row;++i)
    117     {
    118         for(int j=1;j<=50;++j)
    119         {
    120             //cout<<ans[i][j];
    121             printf("%c",'A'-1+blo[ans[i][j]].second);
    122         }
    123         puts("");
    124     }
    125     cout<<endl;
    126 }

      

    D - Unbearable Controversy of Being

      给一个有向图,问图中有多少个图示单元。

      思维+遍历图+水题

      对于每个起始点,找到深度所有为2的点,每个点出现次数计数一下,复杂度O(n^2),答案为每个数的C(cnt,2)求和。

      

     1 #include<bits/stdc++.h>
     2 long long ans=0;
     3 using namespace std;
     4 const int maxn=4000;
     5 inline int cnt(int n){return n*(n-1)/2;}
     6 int n,m,vis[maxn];
     7 vector<int>G[maxn];
     8 void dfs(int now,int dep)
     9 {
    10     if(dep==2)
    11     {
    12         ++vis[now];
    13         return;
    14     }
    15     for(int i=0;i<G[now].size();++i)
    16     {
    17         int to=G[now][i];
    18         dfs(to,dep+1);
    19     }
    20 }
    21 int main()
    22 {
    23     ios::sync_with_stdio(0);
    24     cin>>n>>m;
    25     for(int i=1;i<=m;++i)
    26     {
    27         int a,b;cin>>a>>b;
    28         G[a].push_back(b);
    29     }
    30 
    31     for(int i=1;i<=n;++i)
    32     {
    33         memset(vis,0,sizeof(vis));
    34         dfs(i,0);
    35         for(int j=1;j<=n;++j)
    36         {
    37             if(j==i) continue;
    38             //cout<<vis[j]<<" ";
    39             if(vis[j]>1)
    40             ans+=cnt(vis[j]);
    41         }
    42         //cout<<endl;
    43     }
    44     cout<<ans<<endl;
    45 }

    E水题

    F水题

    G - New Year Permutation

    思维+并查集+个人SB错误(关了流同步用getchar)

    对于每个可以交换的数字集合,按照元素大小排序,到元素对应的集合的时候,从小到大依次取出就ok

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e3;
     4 int fa[maxn],a[maxn];
     5 char plat[maxn][maxn];
     6 int n;
     7 int findx(int x)
     8 {
     9     return x==fa[x]?x:fa[x]=findx(fa[x]);
    10 }
    11 vector<int>per[maxn];
    12 int cnt[maxn],tmp[maxn];
    13 int main()
    14 {
    15     //ios::sync_with_stdio(0);
    16     for(int i=1;i<maxn;++i) fa[i]=i;
    17     cin>>n;
    18     for(int i=1;i<=n;++i)
    19     {
    20         cin>>a[i];
    21     }
    22     
    23     for(int i=1;i<=n;++i)
    24     {
    25         cin>>plat[i]+1;
    26         for(int j=1;j<=n;++j)
    27         {
    28             if(plat[i][j]=='1')
    29             {
    30                 int a=findx(i),b=findx(j);
    31                 if(a!=b)
    32                 {
    33                     fa[b]=a;
    34                 }
    35             }
    36         }
    37     }
    38     for(int i=1;i<=n;++i) tmp[i]=a[i];
    39     for(int i=1;i<=n;++i)
    40     {
    41         int t=findx(i);
    42         per[t].push_back(i);
    43     }
    44     for(int i=1;i<=n;++i)
    45     {
    46         sort(per[i].begin(),per[i].end(),[](int x,int y){return a[x]<a[y];});
    47     }
    48     
    49     for(int i=1;i<=n;++i)
    50     {
    51         int t=findx(i);
    52         cout<<a[per[t][cnt[t]++]]<<" ";
    53     }
    54 }

    H - Alyona and the Tree

    树形dp+思维+深度遍历图

      每个点和每个边都有权值,当两点距离大于子节点长度时,删掉子节点,问最少删除子节点数量

    开始没想明白,,,后来发现:设祖先为X,对于每个子节点的len(X,v),如果这个值小于0,那么从这个字节点开始到它的子节点v',肯定有len(X,v')<len(v,v'),所以维护一个max(0,len(X,v))就可以,当这个值大于子节点权值,删掉子节点,如果子节点不是叶子节点,则移除整棵子树。

     1 #include <bits/stdc++.h>
     2 #define ll long long
     3 #define pii pair<int,int>
     4 using namespace std;
     5 const int maxn=1e5+5;
     6 int a[maxn];
     7 int n,ans;
     8 vector<pii>G[maxn];
     9 void dfs(int fa,int now,ll maxx)
    10 {
    11     if(maxx>a[now]) return;
    12     for(int i=0;i<G[now].size();++i)
    13     {
    14         int to=G[now][i].first,v=G[now][i].second;
    15         if(to==fa) continue;
    16         dfs(now,to,max(maxx+v,1ll*0));
    17     }
    18     ++ans;
    19 }
    20 int main()
    21 {
    22     ios::sync_with_stdio(0);
    23     cin>>n;
    24     for(int i=1;i<=n;++i) cin>>a[i];
    25     for(int i=2;i<=n;++i)
    26     {
    27         int q,w;cin>>q>>w;
    28         G[i].push_back({q,w});
    29         G[q].push_back({i,w});
    30     }
    31     dfs(-1,1,0);
    32     cout<<n-ans;;
    33 }

    J - Resort

      给一个有向图,一些点是特殊点,要求一条最长链使得这条链起点为普通点,终点为特殊点,输出这条链(因为是链所以要求每个普通点出度均为1)。

      一开始想复杂了。。。

      根据输入我们可以注意到:一个点可以有多条出边,但是最多只有只有一条入边!

      所以,我们反向建图:对于每个点,可能有多条入边,但是只能有一条出边

      而且对于每个普通点,满足条件的话要保证其源头只有一个特殊点(此时入度为题目中出度,即保证出度为1),所以每个只被遍历一次,复杂度O(n)。

      然后找到最长的输出即可

      

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e5+5;
     4 int in[maxn];
     5 vector<int>G[maxn],ans[maxn];
     6 int n,hot[maxn];
     7 
     8 void dfs(int h,int now)
     9 {
    10     ans[h].push_back(now);
    11     if(G[now].size())
    12     {
    13         int to=G[now][0];
    14         if(hot[to]) return;
    15         if(in[to]>1) return;
    16         dfs(h,to);
    17     }
    18 }
    19 int main()
    20 {
    21     ios::sync_with_stdio(0);cin>>n;
    22     for(int i=1;i<=n;++i) cin>>hot[i];
    23     for(int i=1;i<=n;++i)
    24     {
    25         int t;cin>>t;
    26         if(t) G[i].push_back(t);
    27         ++in[t];
    28     }
    29     for(int i=1;i<=n;++i)
    30     {
    31         if(hot[i]) dfs(i,i);
    32     }
    33     int maxx=0,maxi;
    34     for(int i=1;i<=n;++i)
    35     {
    36         if(maxx<ans[i].size())
    37         {
    38             maxx=ans[i].size();
    39             maxi=i;
    40         }
    41     }
    42     cout<<maxx<<endl;
    43     reverse(ans[maxi].begin(),ans[maxi].end());
    44     for(int t:ans[maxi])
    45     cout<<t<<" ";
    46 }

    L假的三元环

    M读清题就会做

    N并查集随便搞搞就可以

    Odfs二分图染色一下就ok,复杂度O(n)

     1 #include <bits/stdc++.h>
     2 #define pii pair<int,int>
     3 using namespace std;
     4 const int maxn=2e5+5;
     5 vector<int>G[maxn];
     6 int n,m;
     7 int vis[maxn];
     8 inline int no(int a)
     9 {
    10     return a==1?0:1;
    11 }
    12 void dfs(int fa,int now,int color)
    13 {
    14     for(int to:G[now])
    15     {
    16         if(to==fa) continue;
    17         if(vis[to]==-1)
    18         {
    19             vis[to]=no(color);
    20             dfs(now,to,no(color));
    21         } else{
    22             if(vis[to]==color)
    23             {
    24                 cout<<"-1";
    25                 exit(0);
    26             }
    27             else;
    28         }
    29     }
    30 }
    31 int main()
    32 {
    33     memset(vis,-1,sizeof(vis));
    34     ios::sync_with_stdio(0);
    35     cin>>n>>m;
    36     for(int i=1;i<=m;++i)
    37     {
    38         int a,b;cin>>a>>b;
    39         G[a].push_back(b);
    40         G[b].push_back(a);
    41     }
    42     for(int i=1;i<=n;++i)
    43     {
    44         if(G[i].size()>0 && vis[i]==-1)
    45         {
    46             vis[i]=1;
    47             dfs(-1,i,1);
    48         }
    49     }
    50     int num1=0,num0=0;
    51     for(int i=1;i<=n;++i)
    52     {
    53         if(vis[i]==0) ++num0;
    54         if(vis[i]==1) ++num1;
    55     }
    56     cout<<num0<<endl;
    57     for(int i=1;i<=n;++i) if(vis[i]==0) cout<<i<<" ";
    58     cout<<endl;
    59     cout<<num1<<endl;
    60     for(int i=1;i<=n;++i)
    61     {
    62         if(vis[i]==1) cout<<i<<" ";
    63     }
    64     cout<<endl;;
    65 }
    View Code

    总结:

      1.我不会子写dijkstra  hhhhh(现在会了),对dij有了更深的了解

            (1)开始的写法是假堆,(2)不判断是否入队会T飞(或者队列巨长MLE)(3)队列元素是边数级别的

      2.

        读题很重要!

        读题很重要!

        读题很重要!  

      读题没读好细节就开始瞎jb写导致WA好几发

      3.写代码要专心,否则后果就是debug+思路混乱+效率低

      4.注意long long  (*1)

      5.图论题能不能发现一下题意中隐藏的一些性质呢?(H,J)

  • 相关阅读:
    致应届毕业生——程序员的生存法则 转自CSDN 作者:陈丽辉
    TIOBE 8月份编程语言排行榜,F#强势插入
    C–gcc命令行下的参数
    转载sunboy_2050 Android APK反编译详解(附图)
    转载IT168 分析:Python在Linux平台上的发展前景
    PHP 简单学习过程1
    买火车票必须知道的事
    Delphi PointerMath编译指令
    给DropDownList的DataTextField属性绑定两个字段
    通过HttpModule、httpHandlers防止SQL注入式攻击
  • 原文地址:https://www.cnblogs.com/codeoosacm/p/11278484.html
Copyright © 2011-2022 走看看