ZROI17普及23-A.如煙題解--技巧枚舉
阿新 • • 發佈:2018-08-11
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.如煙題解--技巧枚舉