1. 程式人生 > >ZROI17普及23-A.如煙題解--技巧枚舉

ZROI17普及23-A.如煙題解--技巧枚舉

esp 復雜度 ont con push ret ctype eof tor

  • 題目鏈接

    因版權原因不予提供

  • 分析

    別看這是普及模擬賽,其實基本上是提高難度...像這題做NOIpT1的話也說的過去

    有個很顯然的暴力思路就是枚舉c,a,b,時間復雜度\(O(N^3)\)

    然後正解其實就是改變枚舉順序,我們先枚舉a點,然後將所有可作為c點的點存起來,再從那些c點遍歷得到可行b點統計答案,這樣就不會重復且符合題意

    不過這道題需要仔細讀題,像我這種菜B一開始就理解錯題意了

  • 代碼

    #include <cstdio>
    #include <cstring>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <queue>
    #include <vector>
    #include <cmath>
    #include <iostream>
    #define ll long long 
    #define ri register int 
    #define ull unsigned long long
    using namespace std; 
    template <class T>inline void read(T &x){
      x=0;int ne=0;char c;
      while(!isdigit(c=getchar()))ne=c==‘-‘;
      x=c-48;
      while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
      x=ne?-x:x;return ;
    }
    const int maxn=3005;
    const int inf=0x7fffffff;
    struct Edge{
      int ne,to;
    }edge[maxn<<1],_edge[maxn<<1];
    int h[maxn],num_edge=1;
    inline void add_edge(int f,int to){
      edge[++num_edge].ne=h[f];
      edge[num_edge].to=to;
      h[f]=num_edge;
    }
    int _h[maxn],_num_edge=1;//反向邊 
    inline void _add_edge(int f,int to){
      _edge[++_num_edge].ne=_h[f];
      _edge[_num_edge].to=to;
      _h[f]=_num_edge;
    }
    int n,m,sc,sb;
    bool vis[maxn];
    vector <int> g;
    void _dfs(int now,int fa){
      int v;if(vis[now])return ;
      vis[now]=1;g.push_back(now);
      for(ri i=_h[now];i;i=_edge[i].ne){
          v=_edge[i].to;
          if(v==fa)continue;
          _dfs(v,now);
      }
      return ;    
    }
    void dfs(int now,int fa){
      int v;if(vis[now])return ;
      sb++;vis[now]=1;
      for(ri i=h[now];i;i=edge[i].ne){
          v=edge[i].to;
          if(v==fa)continue;
          dfs(v,now);
      }
      return ;    
    }
    int main(){
      int T,x,y,z;
      srand(19260817);//悶聲發大財 預祝長者大壽 Long Live Jiang !!! 
      read(T);
      while(T--){
          ll ans=0;
          read(n),read(m);
          memset(h,0,sizeof(h));
          memset(_h,0,sizeof(_h));
          num_edge=_num_edge=1;       
          for(ri i=1;i<=m;i++){
              read(x),read(y);
              add_edge(x,y);
              _add_edge(y,x);
          }
          int ss=(n+1)*sizeof(bool);
          for(ri i=1;i<=n;i++){
              memset(vis,0,ss);
              g.clear();
              _dfs(i,0);
              memset(vis,0,ss);
              for(ri j=0;j<g.size();j++){
                  sb=0;
                  dfs(g[j],0); 
                  ans+=sb;
                  //printf("--%d %d %d\n",g[j],i,sb);
              }
          }
          printf("%lld\n",ans);
      }
      return 0;
    }

ZROI17普及23-A.如煙題解--技巧枚舉