2018.10.21 練習賽 樹專練
阿新 • • 發佈:2018-10-31
T1 樹
題解:
記錄樹上字首和,每次加入新字首和就二分一下字首和陣列看有無滿足\(sum[now]-s\)的數在裡面,因為\(sum\)必定是單調的,就亂搞完畢;
\(code\):
#include<cstdio> #include<algorithm> #include<ctype.h> #include<vector> #include<queue> #include<cstring> #include<map> #include<stdlib.h> #include<ctime> #define lowbit(x) (x&-x) #define ll long long #define ld double #define mod 998244353 using namespace std; char buf[1<<20],*p1,*p2; inline char gc() { return getchar(); return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++; } template<typename T> inline void read(T &x) { char tt; bool flag=0; while(!isdigit(tt=gc())&&tt!='-'); tt=='-'?(flag=1,x=0):(x=tt-'0'); while(isdigit(tt=gc())) x=x*10+tt-'0'; if(flag) x=-x; } const int maxn=1e5+2; int n,s; vector<int>G[maxn]; bool root[maxn]; int w[maxn],sum[maxn],ans; void dfs(int x,int dep) { sum[dep]=sum[dep-1]+w[x]; if(sum[lower_bound( sum,sum+dep+1,sum[dep]-s)-sum]==sum[dep]-s) ans++; for(int i=G[x].size()-1;i>=0;i--) { int p=G[x][i]; dfs(p,dep+1); } sum[dep]=0; } int main() { read(n),read(s); for(int i=1;i<=n;i++) read(w[i]); for(int i=1;i<n;i++) { int x,y; read(x),read(y); G[x].push_back(y); root[y]=1; } for(int i=1;i<=n;i++) if(!root[i]) {dfs(i,1);break;} printf("%d",ans); return 0; }
T2 聯通塊計數
題解:
樹DP=_=
\(code:\)
#include<cstdio> #include<algorithm> #include<ctype.h> #include<vector> #include<queue> #include<cstring> #include<map> #include<stdlib.h> #include<ctime> #define lowbit(x) (x&-x) #define ll long long #define ld double #define mod 998244353 using namespace std; char buf[1<<20],*p1,*p2; inline char gc() { // return getchar(); return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++; } template<typename T> inline void read(T &x) { char tt; bool flag=0; while(!isdigit(tt=gc())&&tt!='-'); tt=='-'?(flag=1,x=0):(x=tt-'0'); while(isdigit(tt=gc())) x=x*10+tt-'0'; if(flag) x=-x; } inline ll add(ll a,ll b){return a+b<mod?a+b:a+b-mod;} inline ll mul(ll a,ll b){return a*b<mod?a*b:a*b%mod;} inline ll sub(ll a,ll b){return a-b<0?a-b+mod:a-b;} const int maxn=2002; struct node{ ll x,id; inline node(ll a=0,ll b=0) {x=a,id=b;} inline bool operator<(node a)const {return x==a.x?a.id<a.id:x<a.x;} }a[maxn]; ll n,k,ans,w[maxn]; vector<ll>G[maxn]; bool book[maxn]; ll dfs(ll x,ll pre,ll lim) { int ret=1; for(int i=G[x].size()-1;i>=0;i--) { int p=G[x][i]; if(p==pre||book[p]||w[p]>lim) continue; ret=mul(ret,dfs(p,x,lim)); } // printf("%d\n",lim); return ret+=(pre!=0); } int main() { read(n),read(k); for(int i=1;i<=n;i++) { ll x; read(x);w[i]=x; a[i]=node(x,i); }sort(a+1,a+1+n); for(int i=1;i<n;i++) { ll x,y; read(x),read(y); G[x].push_back(y); G[y].push_back(x); } for(int i=1;i<=n;i++) { if(book[a[i].id]) continue; book[a[i].id]=1; ans=add(ans,dfs(a[i].id,0,a[i].x+k)); // printf("%d\n",ans); } printf("%lld",ans); return 0; }
T2 電壓
題解:
題意為去掉一條邊,看此圖是否仍為一個二分圖;
我們考慮去掉的這條邊必定是所有奇環的交,且不能在任何的偶環上,\(tarjan\)找出所有環(這裡的所有環是指寫出的演算法所能找出的環,並非真正意義上的所有環)
每當我們遇到一條返祖邊,差分記錄環覆蓋的邊,統計答案時滿足前面我們所給的條件即可;
\(code:\)
#include<cstdio> #include<algorithm> #include<ctype.h> #include<vector> #include<queue> #include<cstring> #include<map> #include<stdlib.h> #include<ctime> #define lowbit(x) (x&-x) #define ll long long #define ld double #define mod 998244353 using namespace std; char buf[1<<20],*p1,*p2; inline char gc() { // return getchar(); return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++; } template<typename T> inline void read(T &x) { char tt; bool flag=0; while(!isdigit(tt=gc())&&tt!='-'); tt=='-'?(flag=1,x=0):(x=tt-'0'); while(isdigit(tt=gc())) x=x*10+tt-'0'; if(flag) x=-x; } struct node{ int x,id; inline node(int a=0,int b=0) {x=a,id=b;} }; const int maxn=1e5+2; int n,m,dep[maxn],tot; int cnt[maxn][2]; //0 1 odd //0 0 eve vector<node>G[maxn]; void dfs(int x,int pre) { for(int i=G[x].size()-1;i>=0;i--) { int p=G[x][i].x,id=G[x][i].id; if(id==pre) continue; if(!dep[p]) { dep[p]=dep[x]+1;dfs(p,id); cnt[x][0]+=cnt[p][0]; cnt[x][1]+=cnt[p][1]; } else if(dep[p]<=dep[x]) { if((dep[x]-dep[p])&1) cnt[x][0]++,cnt[p][0]--; else cnt[x][1]++,cnt[p][1]--,tot++; } } } int main() { // freopen("voltage.in","r",stdin); read(n),read(m); for(int i=1;i<=m;i++) { int x,y; read(x),read(y); G[x].push_back(node(y,i)); G[y].push_back(node(x,i)); } int ans=0; for(int i=1;i<=n;i++) if(!dep[i]) dep[i]=1,dfs(i,0); for(int i=1;i<=n;i++) if(dep[i]!=1&&!cnt[i][0]&&cnt[i][1]==tot) ans++; printf("%d",ans+(tot==1)); }