数据结构&&图论板子
2017-11-08 11:40
288 查看
板子日DAY1
以下均为洛谷模板
线段树
(区间修改区间求和)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define ll long long ll read(){ char c=getchar(); ll f=1,ans=0; while(!isdigit(c)){ if(c=='-')f=-1; c=getchar(); } while(isdigit(c)){ ans=ans*10+(c-'0'); c=getchar(); } return ans*f; } const int maxn=1e5+10; #define lson x<<1 #define rson x<<1|1 ll sum[maxn<<2],tag[maxn<<2],num[maxn<<2],a[maxn]; inline void pushup(int x){ sum[x]=sum[lson]+sum[rson]; } inline void pushdown(int x){ if(tag[x]){ tag[lson]+=tag[x]; tag[rson]+=tag[x]; sum[lson]+=tag[x]*num[lson]; sum[rson]+=tag[x]*num[rson]; tag[x]=0; } } void build(int l,int r,int x){ if(l==r){ sum[x]=a[l]; num[x]=1; return ; } ll mid=l+r>>1; build(l,mid,lson); build(mid+1,r,rson); pushup(x); num[x]=num[lson]+num[rson]; } void modify(int l,int r,int ql,int qr,int x,int k){ if(ql<=l&&r<=qr){ sum[x]+=num[x]*k; tag[x]+=k; return ; } pushdown(x); ll mid=l+r>>1; if(ql<=mid) modify(l,mid,ql,qr,lson,k); if(mid<qr) modify(mid+1,r,ql,qr,rson,k); pushup(x); } ll query(int l,int r,int ql,int qr,int x){ if(ql<=l&&r<=qr){ return sum[x]; } pushdown(x); ll mid=l+r>>1; ll ans=0; if(ql<=mid) ans+=query(l,mid,ql,qr,lson); if(qr>mid) ans+=query(mid+1,r,ql,qr,rson); return ans; } int main(){ int n=read(),m=read(); for(int i=1;i<=n;i++){ a[i]=read(); } build(1,n,1); for(int i=1;i<=m;i++){ int ord=read(); if(ord==1){ int x=read(),y=read(),k=read(); modify(1,n,x,y,1,k); } else { int x=read(),y=read(); cout<<query(1,n,x,y,1)<<"\n"; } } }
树状数组
(单点修改区间求和)
const int maxn=500100; int c[maxn],n,m; int lowbit(int x){ return x&(-x); } void add(int x,int k){ while(x<=n){ c[x]+=k; x+=lowbit(x); } } ll query(int x){ ll ans=0; while(x>0){ ans+=c[x]; x-=lowbit(x); } return ans; } int main() { //ios::sync_with_stdio(false); n=read(),m=read(); for(int i=1;i<=n;i++){ int a=read(); add(i,a); } for(int i=1;i<=m;i++){ int ord=read(); if(ord==1){ int x=read(),k=read(); add(x,k); }else { int x=read(),y=read(); cout<<query(y)-query(x-1)<<"\n"; } } return 0; }
单源最短路
SPFA
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<queue> #include<cstdlib> #include<cmath> #include<map> #include<set> #define ll long long using namespace std; ll read() { ll ans=0; bool b=1; char c=getchar(); while(!isdigit(c)) { if(c=='-')b=0; c=getchar(); } while(isdigit(c)) { ans=ans*10+(c-'0'); c=getchar(); } if(b)return ans; else return -ans; } const int maxn=500100; struct rec{ int t,next,w; }e[maxn<<1]; int now[maxn],f[maxn],dis[maxn],p,pre[maxn]; inline void add(int a,int b,int c){ p+ 15f6e +; e[p].t=b; e[p].w=c; e[p].next=now[a]; now[a]=p; } void dfs(int x){ if(pre[x])dfs(pre[x]); cout<<x<<" "; } int main() { //ios::sync_with_stdio(false); queue<int> que; int n=read(),m=read(),s=read(); for(int i=1;i<=m;i++){ int a=read(),b=read(),c=read(); add(a,b,c); //add(b,a,c); 一定要看是单向边还是双向边!!! } for(int i=1;i<=n;i++){ dis[i]=0x7fffffff; } dis[s]=0; que.push(s);f[s]=1; while(!que.empty()){ int u=que.front(); que.pop(); f[u]=0; for(int i=now[u];i;i=e[i].next){ int v=e[i].t; if(dis[u]+e[i].w<dis[v]){ dis[v]=dis[u]+e[i].w; pre[v]=u; if(!f[v]){ f[v]=1; que.push(v); } } } } for(int i=1;i<=n;i++){ cout<<dis[i]<<" "; //dfs(i);cout<<endl; //输出路径 } return 0; }
朴素的Dijkstra
for(int i=1;i<=n;i++){ dis[i]=0x7fffffff; } dis[s]=0; for(int i=1;i<=n;i++){ int minn=0x7fffffff,u=-1; for(int j=1;j<=n;j++){ if(dis[j]<minn&&!vis[j]){ minn=dis[j],u=j; } } if(u==-1)break; vis[u]=1; for(int j=now[u];j;j=e[j].next){ int v=e[j].t; if(!vis[v]) dis[v]=min(dis[u]+e[j].w,dis[v]); } }
堆优化的DJ
typedef pair<int,int> kkk; priority_queue<kkk,vector<kkk>,greater<kkk> > que; int n=read(),m=read(),s=read(); for(int i=1;i<=m;i++){ int a=read(),b=read(),c=read(); add(a,b,c); } for(int i=1;i<=n;i++){ dis[i]=0x7fffffff; } dis[s]=0; que.push(make_pair(0,s)); while(!que.empty()){ kkk top=que.top(); int u=top.second; que.pop(); if(vis[u])continue; vis[u]=1; for(int i=now[u];i;i=e[i].next){ int v=e[i].t; if(dis[v]>dis[u]+e[i].w){ dis[v]=dis[u]+e[i].w; que.push(make_pair(dis[v],v)); } } }
树链剖分
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; #define ll long long ll read(){ char c=getchar(); ll f=1,ans=0; while(!isdigit(c)){ if(c=='-')f=-1; c=getchar(); } while(isdigit(c)){ ans=ans*10+(c-'0'); c=getchar(); } return ans*f; } const int maxn=1e5+10; #define lson x<<1 #define rson x<<1|1 ll sum[maxn<<2],tag[maxn<<2],num[maxn<<2],a[maxn],r,n,m,p; inline void pushup(int x){ sum[x]=sum[lson]+sum[rson]; } inline void pushdown(int x){ if(tag[x]){ tag[lson]+=tag[x]; tag[lson]%=p; tag[rson]+=tag[x]; tag[rson]%=p; sum[lson]+=tag[x]*num[lson]; sum[lson]%=p; sum[rson]+=tag[x]*num[rson]; sum[rson]%=p; tag[x]=0; } } void build(int l,int r,int x){ if(l==r){ sum[x]=a[l]; num[x]=1; return ; } ll mid=l+r>>1; build(l,mid,lson); build(mid+1,r,rson); pushup(x); num[x]=num[lson]+num[rson]; } void modify(int l,int r,int ql,int qr,int x,int k){ if(ql<=l&&r<=qr){ sum[x]+=num[x]*k; sum[x]%=p; tag[x]+=k; tag[x]%=p; return ; } pushdown(x); ll mid=l+r>>1; if(ql<=mid) modify(l,mid,ql,qr,lson,k); if(mid<qr) modify(mid+1,r,ql,qr,rson,k); pushup(x); } ll query(int l,int r,int ql,int qr,int x){ if(ql<=l&&r<=qr){ return sum[x]; } pushdown(x); ll mid=l+r>>1; ll ans=0; if(ql<=mid) ans+=query(l,mid,ql,qr,lson); ans%=p; if(qr>mid) ans+=query(mid+1,r,ql,qr,rson); ans%=p; return ans; } ll size[maxn],top[maxn],son[maxn],dep[maxn],fa[maxn],now[maxn],dfn[maxn],cnt,w[maxn],pp; struct rec{ int t,next; }e[maxn<<2]; void dfs_1(int x){ size[x]=1; for(int i=now[x];i;i=e[i].next){ int v=e[i].t; if(v!=fa[x]){ fa[v]=x; dep[v]=dep[x]+1; dfs_1(v); size[x]+=size[v]; if(size[son[x]]<size[v])son[x]=v; } } } void dfs_2(int x,int t){ dfn[x]=++cnt; a[cnt]=w[x]; top[x]=t; if(son[x])dfs_2(son[x],t); for(int i=now[x];i;i=e[i].next){ int v=e[i].t; if(v!=fa[x]&&v!=son[x]){ dfs_2(v,v); } } } void cal(int a,int b,int k){ while(top[a]!=top[b]){ if(dep[top[a]]<dep[top[b]])a^=b^=a^=b; modify(1,n,dfn[top[a]],dfn[a],1,k); a=fa[top[a]]; } if(dep[a]>dep[b])a^=b^=a^=b; modify(1,n,dfn[a],dfn[b],1,k); } ll call(int a,int b){ ll ans=0; while(top[a]!=top[b]){ if(dep[top[a]]<dep[top[b]])a^=b^=a^=b; ans+=query(1,n,dfn[top[a]],dfn[a],1); ans%=p; a=fa[top[a]]; } if(dep[a]>dep[b])a^=b^=a^=b; ans+=query(1,n,dfn[a],dfn[b],1); ans%=p; return ans; } void add(int a,int b){ pp++; e[pp].t=b; e[pp].next=now[a]; now[a]=pp; } int main(){ n=read(),m=read(),r=read(),p=read(); for(int i=1;i<=n;i++){ w[i]=read(); } for(int i=1;i<n;i++){ int a=read(),b=read(); add(a,b); add(b,a); } dfs_1(r); dfs_2(r,r); build(1,n,1); for(int i=1;i<=m;i++){ int ord=read(); if(ord==1){ int x=read(),y=read(),k=read(); cal(x,y,k); } else if(ord==2){ int x=read(),y=read(); cout<<call(x,y)<<"\n"; } else if(ord==3){ int x=read(),k=read(); modify(1,n,dfn[x],dfn[x]+size[x]-1,1,k); } else { int x=read(); cout<<query(1,n,dfn[x],dfn[x]+size[x]-1,1)<<"\n"; } } }
三分法
double xishu[20]; int n; double poww(double x,int p){ double ans=1.0; for(;p;p>>=1,x=x*x){ if(p&1){ ans=ans*x; } } return ans; } double f(double x){ double ans=0.0; for(int i=0;i<=n;i++){ ans+=poww(x,i)*xishu[i]; } return ans; } const double eps=1e-7; int main() { //ios::sync_with_stdio(false); n=read(); double l,r; cin>>l>>r; for(int i=n;i>=0;i--){ cin>>xishu[i]; } double midl,midr; while(fabs(r-l)>eps&&l<=r){ midl=(r+l)/2,midr=(r+midl)/2; if(f(midl)>f(midr)) r=midr; else l=midl; } printf("%.5f",l); return 0; }
并查集
const int maxn=10100; int fa[maxn]; int find(int x){ return fa[x]==x? x : fa[x]=find(fa[x]); } int main() { //ios::sync_with_stdio(false); int n=read(),m=read(); for(int i=1;i<=n;i++){ fa[i]=i; } for(int i=1;i<=m;i++){ int ord=read(); if(ord==1){ int a=read(),b=read(); fa[find(a)]=find(b); } else { int a=read(),b=read(); if(find(a)==find(b))cout<<"Y\n"; else cout<<"N\n"; } } return 0; }
最小生成树
(kruskal)
void kruskal(){ for(int i=1;i<=n;i++){ fa[i]=i; } int ans=0,sum=0; sort(e+1,e+p+1,cmp); for(int i=1;i<=p;i++){ if(find(e[i].f)!=find(e[i].t)){ fa[find(e[i].f)]=find(e[i].t); ans+=e[i].w; sum++; if(sum==n-1)break; } } if(sum==n-1)cout<<ans; else cout<<"NO solution"; return; }
字符串哈希
(哈希表)
const int base = 2000327; const int MOD = 1e5+7; struct rec{ string s; rec *next; rec():next(NULL) { } }hash[MOD]; int find(rec &a,string s){ if(a.next==NULL){ a.s=s; a.next=new rec; return 0; } if(a.s==s)return 1; else return find(*(a.next),s); } bool haxi(string s){ unsigned long long hia; for(int i=0;i<s.size();i++){ hia+=base*hia+s[i]; //注意这里 } hia%=MOD; if(find(hash[hia],s))return 0; else return 1; } int main() { //ios::sync_with_stdio(false); int n=read(),sum=0; for(int i=1;i<=n;i++){ string s; cin>>s; if(haxi(s)) sum++; } cout<<sum; return 0; }
(双模)//拒绝吐槽模数
const int MOD1 = 2000327; const int MOD2 = 2000321; const int base = 19260817; int hash1[MOD1],hash2[MOD2]; int find(unsigned long long haxishu){ unsigned ll ha1=haxishu%MOD1; unsigned ll ha2=haxishu%MOD2; if(hash1[ha1]&&hash2[ha2]){ return 1; } else { hash1[ha1]=1; hash2[ha2]=1; return 0; } } bool haxi(string s){ unsigned long long hia; for(int i=0;i<s.size();i++){ hia=base*hia+s[i]; } if(find(hia))return 0; else return 1; }
LCA
(树链剖分)
const int maxn=500100; struct rec{ int f,t,next; }e[maxn<<1]; int fa[maxn],size[maxn],top[maxn],son[maxn],dep[maxn],cnt,n,p,m,s,now[maxn]; void add(int a,int b){ p++; e[p].t=b; e[p].next=now[a]; now[a]=p; } void dfs_1(int x){ size[x]=1; for(int i=now[x];i;i=e[i].next){ int v=e[i].t; if(v!=fa[x]){ fa[v]=x; dep[v]=dep[x]+1; dfs_1(v); size[x]+=size[v];// size[v] 噢不是x if(size[son[x]]<size[v])son[x]=v; } } } void dfs_2(int x,int t){ top[x]=t; if(son[x])dfs_2(son[x],t); for(int i=now[x];i;i=e[i].next){ int v=e[i].t; if(v!=fa[x]&&v!=son[x]){ dfs_2(v,v); } } } int lca(int a,int b){ while(top[a]!=top[b]){ if(dep[top[a]]<dep[top[b]]){ a^=b^=a^=b; } a=fa[top[a]]; } if(dep[a]>dep[b])a^=b^=a^=b; return a; } int main() { //ios::sync_with_stdio(false); n=read(),m=read(),s=read(); for(int i=1;i<n;i++){ int a=read(),b=read(); add(a,b); add(b,a); } //fa[s]=s; dfs_1(s); dfs_2(s,s); for(int i=1;i<=m;i++){ int a=read(),b=read(); cout<<lca(a,b)<<"\n"; } return 0; }
(倍增)
const int maxn=501000; struct rec{ int f,t,next; }e[maxn<<1]; int n,m,s,now[maxn],fa[maxn][20],dep[maxn],p;//注意数组大小 后边for循环不要越界!! void add(int a,int b){ p++; e[p].t=b; e[p].next=now[a]; now[a]=p; } void dfs(int x){ for(int i=now[x];i;i=e[i].next){ int v=e[i].t; if(v!=fa[x][0]){ fa[v][0]=x; dep[v]=dep[x]+1; dfs(v); } } } void befor(){ dfs(s);fa[s][0]=s;//根节点父亲是自己 for(int i=1;i<=17;i++){ for(int j=1;j<=n;j++){ fa[j][i]=fa[fa[j][i-1]][i-1]; } } } int lca(int a,int b){ if(dep[a]<dep[b]){ a^=b^=a^=b; } for(int i=17;i>=0;i--){ if(dep[fa[a][i]]>=dep[b]){ a=fa[a][i]; } } if(a==b)return a; for(int i=17;i>=0;i--){ if(fa[a][i]!=fa[b][i]){ a=fa[a][i]; b=fa[b][i]; } } a=fa[a][0]; return a; } int main() { //ios::sync_with_stdio(false); n=read(),m=read(),s=read(); for(int i=1;i<n;i++){ int a=read(),b=read(); add(a,b); add(b,a); } befor(); for(int i=1;i<=m;i++){ int a=read(),b=read(); cout<<lca(a,b)<<"\n"; } return 0; }
负环
dfs_spfa判断
const int maxn=501000; struct rec{ int f,t,next,w; }e[maxn<<1]; int n,m,s,now[maxn],dis[maxn],p,vis[maxn]; bool flag; void add(int a,int b,int c){ p++; e[p].t=b; e[p].next=now[a]; e[p].w=c; now[a]=p; } void dfs_spfa(int u){ vis[u]=1; for(int i=now[u];i;i=e[i].next){ int v=e[i].t; if(dis[v]>dis[u]+e[i].w){ dis[v]=dis[u]+e[i].w; if(vis[v]||flag){ flag=1; return; } else dfs_spfa(v); } } vis[u]=0; } int main() { //ios::sync_with_stdio(false); int T=read(); while(T--){ memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); memset(now,0,sizeof(now)); p=0;flag=0; //记得每次清零! n=read(),m=read(); for(int i=1;i<=m;i++){ int a=read(),b=read(),c=read(); add(a,b,c); if(c>=0)add(b,a,c); } for(int i=1;i<=n;i++){ dfs_spfa(i); if(flag)break; } if(flag)cout<<"YE5\n"; else cout<<"N0\n"; } return 0; }
二分图匹配
(匈牙利算法)
const int maxn=501000; struct rec{ int f,t,next; }e[maxn<<1]; int n,m,s,now[maxn],p,match[maxn],check[maxn],sum=0; void add(int a,int b){ p++; e[p].t=b; e[p].next=now[a]; now[a]=p; } bool dfs(int x){ for(int i=now[x];i;i=e[i].next){ int v=e[i].t; if(!check[v]){ //先检查是否被check过 check[v]=1;//写在前面噢记得 if(!match[v]||dfs(match[v])){ // dfs的是match[v]而不是v match[x]=v; match[v]=x; return 1; } } } return 0; } int main() { //ios::sync_with_stdio(false); int n=read(),m=read(),e=read(); for(int i=1;i<=e;i++){ int a=read(),b=read(); if(b>m)continue; add(a,b+n); } for(int i=1;i<=n;i++){ if(!match[i]){ memset(check,0,sizeof(check));//每次初始化 if(dfs(i)) sum++; } } cout<<sum; return 0; }
缩点
(tarjan)const int maxn=1e5+7; struct rec{ int t,f,next; }e1[maxn<<1],e2[maxn<<1]; int now1[maxn],now2[maxn],p,pp,dfn[maxn],low[maxn],cnt,bcnt,w[maxn],bw[maxn],belong[maxn],instack[maxn],dp[maxn]; void add(int a,int b,rec e[],int now[],int &p){ p++; e[p].t=b; e[p].f=a; e[p].next=now[a]; now[a]=p; } stack <int> st; void tarjan(int x){ dfn[x]=low[x]=++cnt; instack[x]=1; st.push(x); for(int i=now1[x];i;i=e1[i].next){ int v=e1[i].t; if(!dfn[v]){ tarjan(v); //tarjan 不是 dfs low[x]=min(low[v],low[x]); } else if(instack[v]) low[x]=min(low[x],dfn[v]); } if(low[x]==dfn[x]){ int j; ++bcnt; do{ j=st.top(); st.pop(); belong[j]=bcnt; bw[bcnt]+=w[j]; instack[j]=0; //五项 一项都不能丢! }while(x!=j); } } int dfs(int x){ if(dp[x])return dp[x]; for(int i=now2[x];i;i=e2[i].next){ int v=e2[i].t; dp[x]=max(dfs(v),dp[x]); } dp[x]+=bw[x]; //加bw 不是w return dp[x]; } int main() { //ios::sync_with_stdio(false); int n=read(),m=read(); for(int i=1;i<=n;i++){ w[i]=read(); } for(int i=1;i<=m;i++){ int a=read(),b=read(); add(a,b,e1,now1,p); } for(int i=1;i<=n;i++){ if(!dfn[i])tarjan(i); } for(int i=1;i<=m;i++){ if(belong[e1[i].f]!=belong[e1[i].t]){ add(belong[e1[i].f],belong[e1[i].t],e2,now2,pp); } } //记得重新加一次边 int ans=0; for(int i=1;i<=bcnt;i++){ if(!dp[i]){ ans=max(dfs(i),ans); } } cout<<ans; return 0; }
割点
(tarjan)
void tarjan(int x){ dfn[x]=low[x]=++cnt; for(int i=now1[x];i;i=e1[i].next){ int v=e1[i].t; if(!dfn[v]){ fa[v]=x; tarjan(v); //tarjan 不是 dfs size[x]++; low[x]=min(low[v],low[x]); if(low[v]>=dfn[x]&&fa[x]!=0) is[x]=1;//low [v] 不是low [x] !!! } else if(v!=fa[x]) low[x]=min(low[x],dfn[v]); } if(size[x]>1&&fa[x]==0) is[x]=1; }
相关文章推荐
- ACM: 图论题 poj3259 bellman_ford…
- ACM: 图论题 poj 2253 (poj上的dou…
- ACM: spfa求解 图论题 (对差分约束…
- 【图论】最大密度子图&权闭合图
- hdu 5348 MZL's endless loop(dfs+图论)
- HDU 1818 It's not a Bug, It's a Feature! (图论SPFA)
- 不要修改dtsi,修改自己板子的dts,通过 &label 语句修改子文件里已经存在的节点
- (终端,板子...)Linux下模拟CPU/内存占用工具打包发布+使用说明-cpuup&memup
- HDU 1166 敌兵布阵(线段数&树状数组板子题)
- 对mini2440板子附带的《Mini2440&nbsp;L…
- POJ 图论---1_Uriel's Corner Uriel's Coding & Learning & Cubing Zone
- poj 3281 Dining 【图论-网络流-最大流-EK&Ford-Fulkerson】
- ACM: 图论题poj 1860 (没心情复习…
- ACM: 图论题 poj 1062 (邻接矩阵+d…
- ACM: 图论题 poj 3…
- POJ1659 Frogs' Neighborhood ACM解题报告(图论基础 邻接矩阵)
- 【图论】最短路径&&最小生成树问题
- 数论&&快排&&dp板子
- 【例题】【图论&DP(状压)】NKOJ 1905 慢跑小路 【S2状态压缩】
- ACM: 图论基础题 poj2387 裸露的di…