主要内容:
1.最小瓶颈路
2.kruskal 重构树
3.差分约束系统
4.强连通分量
5.DFS树
6.kosaraju算法求SCC
7.tarjan算法求SCC
8.SAT问题
最小瓶颈路
模板:
#include<bits/stdc++.h> #define re return #define lowbit(x) (x&(-x)) #define dec(i,l,r) for(int i=l;i>=r;--i) #define inc(i,l,r) for(int i=l;i<=r;++i) const int maxn=1005,maxm=200005; using namespace std; template<typename T>inline void rd(T&x) { char c; bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } int n,m,q,deep[maxn],hd[maxn],fa[maxn],f[maxn][25],dis[maxn][25]; struct node { int fr,to,nt,val; bool operator<(node x)const { re val<x.val; } } e[maxn<<1],e1[maxm]; inline int find(int x) { re x==fa[x]?x:fa[x]=find(fa[x]); } inline void dfs(int x,int fa) { deep[x]=deep[fa]+1; for(int i=0; f[f[x][i]][i]; ++i) { f[x][i+1]=f[f[x][i]][i]; dis[x][i+1]=max(dis[x][i],dis[f[x][i]][i]); } for(int i=hd[x]; i; i=e[i].nt) { int v=e[i].to; if(v!=fa) { f[v][0]=x; dis[v][0]=e[i].val; dfs(v,x); } } } inline int LCA(int x,int y) { int ans=0; if(deep[x]<deep[y])x^=y^=x^=y; dec(i,24,0) if(deep[f[x][i]]>=deep[y]) { ans=max(ans,dis[x][i]); x=f[x][i]; } if(x==y)re ans; dec(i,24,0) if(f[x][i]!=f[y][i]) { ans=max(ans,dis[x][i]); ans=max(ans,dis[y][i]); x=f[x][i]; y=f[y][i]; } re max(ans,max(dis[x][0],dis[y][0])); } int main() { int x,y,z; rd(n),rd(m); rd(q); inc(i,1,m) { rd(x),rd(y),rd(z); e1[i]=(node) { x,y,0,z }; } sort(e1+1,e1+m+1); int cnt=0,k=0; inc(i,1,n)fa[i]=i; inc(i,1,m) { int x=e1[i].fr,y=e1[i].to,w=e1[i].val; int f1=find(fa[x]),f2=find(fa[y]); if(f1!=f2) { e[++k]=(node) { x,y,hd[x],w }; hd[x]=k; e[++k]=(node) { y,x,hd[y],w }; hd[y]=k; ++cnt; fa[f1]=f2; if(cnt==n-1)break; } } inc(i,1,n) if(!deep[i])dfs(i,0); int s,t; inc(i,1,q) { rd(s),rd(t); if(i==27) x=1; if(find(s)!=find(t))printf("-1\n"); else printf("%d\n",LCA(s,t)); } return 0; }
kruskal 重构树
模板:
#include<bits/stdc++.h> using namespace std; #define f(i, a, b) for(int i = (a); i <= (b); i++) #define cl(i, n) i.clear(),i.resize(n); #define endl '\n' typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; const int inf = 1e9; int N = 200000; int n,m,q; vector<int> g[200010]; int lg2[200010]; vector<int> dep, dfn; vector<int> stmx[200010], stmn[200010], anc[200010]; int cha[200010]; struct rec { int x,y,z; } edge[500010]; bool operator<(rec a,rec b) { return a.z<b.z; } int qz[200010]; int fa[200010]; int get(int x) { if(fa[x]==x)return x; else return fa[x] = get(fa[x]); } int kruskal() { int cnt = n; f(i,1,2*n)fa[i]=i; f(i, 1, m) { int x = get(edge[i].x); int y = get(edge[i].y); if(x == y)continue; else { int z = ++cnt; g[x].push_back(z); g[y].push_back(z); g[z].push_back(x); g[z].push_back(y); fa[x]=z; fa[y]=z; qz[z] = edge[i].z; } } return cnt; } int ccnt; void dfs(int now, int fa) { dfn[now] = ++ccnt; dep[now] = dep[fa] + 1; anc[now][0] = fa; f(i, 1, lg2[dep[now]] - 1) { anc[now][i] = anc[anc[now][i - 1]][i - 1]; } f(i, 0, (int)g[now].size() -1 ) { if(g[now][i] != fa) dfs(g[now][i], now); } } int lca(int qx, int qy) { if(dep[qx] < dep[qy]) swap(qx, qy); while(dep[qx] > dep[qy]) { qx = anc[qx][lg2[dep[qx]-dep[qy]] - 1]; } if(qx == qy) return qx; for(int k = lg2[dep[qx]] - 1; k >= 0; k--) { if(anc[qx][k] != anc[qy][k]) { qx = anc[qx][k]; qy = anc[qy][k]; } } return anc[qx][0]; } void STmx_prework() { f(i, 1, n) stmx[i][0] = dfn[i]; int mx = log(n) / log(2); f(j, 1, mx) { int mxi = n - (1 << j) + 1; f(i, 1, mxi) { stmx[i][j] = max(stmx[i][j - 1], stmx[i + (1 << (j - 1))][j - 1]); } } } void STmn_prework() { f(i, 1, n) stmn[i][0] = dfn[i]; int mx = log(n) / log(2); f(j, 1, mx) { int mxi = n - (1 << j) + 1; f(i, 1, mxi) { stmn[i][j] = min(stmn[i][j - 1], stmn[i + (1 << (j - 1))][j - 1]); } } } int querymx(int l, int r) { int mx = log(r - l + 1) / log(2); int ans; ans = max(stmx[l][mx], stmx[r - (1 << mx) + 1][mx]); return ans; } int querymn(int l, int r) { int mx = log(r - l + 1) / log(2); int ans; ans = min(stmn[l][mx], stmn[r - (1 << mx) + 1][mx]); return ans; } int main() { ios::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL); f(i, 1, N) lg2[i] = lg2[i - 1] + (1 << lg2[i - 1] == i); int t; cin >> t; while(t--) { cin>>n>>m>>q; f(i, 1, m) { int u, v; cin >> u >> v; edge[i].x = u, edge[i].y = v, edge[i].z = i; } sort(edge+1,edge+m+1); f(i,1,2*n)g[i].clear(); int root = kruskal(); n=2*n; cl(dep, n+10); cl(dfn,n+10); f(i,0,n+9) { cl(anc[i],30); cl(stmx[i],30); cl(stmn[i],30); } dfs(root, 0); STmx_prework(); STmn_prework(); f(i,1,n) cha[dfn[i]] = i; f(i, 1, q) { int l, r; cin >> l >> r; if(l == r) { cout << 0 << " "; continue; } int mx = querymx(l, r), mn = querymn(l, r); int lcaa = lca(cha[mx], cha[mn]); cout << qz[lcaa] <<" "; } cout << endl; } return 0; }
差分约束系统
模板:
#include<bits/stdc++.h> using namespace std; queue<long long>p; long long n,m,a,b,c,bj[5005],sz[5005],cs[5005],wz; long long ans,head[5005]; struct hehe { long long w,cd,syg; } lsqxx[10005]; void add(long long t,long long w,long long cd) { ans++; lsqxx[ans].w=w; lsqxx[ans].cd=cd; lsqxx[ans].syg=head[t]; head[t]=ans; } bool qg() { for(int i=1; i<=n; i++) { sz[i]=1000; } while(p.empty()==false) { wz=p.front(); bj[wz]=0; p.pop(); for(int i=head[wz]; i!=0; i=lsqxx[i].syg) { if(sz[lsqxx[i].w]>sz[wz]+lsqxx[i].cd) { sz[lsqxx[i].w]=sz[wz]+lsqxx[i].cd; if(bj[lsqxx[i].w]==0) { bj[lsqxx[i].w]=1; cs[lsqxx[i].w]++; if(cs[lsqxx[i].w]==n) { return false; } p.push(lsqxx[i].w); } } } } return true; } int main() { cin>>n>>m; for(int i=1; i<=n; i++) { add(0,i,0); } for(int i=0; i<m; i++) { cin>>a>>b>>c; add(b,a,c); } p.push(0); if(qg()==false) { cout<<"NO"<<endl; } else { for(int i=1; i<=n; i++) { cout<<sz[i]<<" "; } cout<<endl; } return 0; }
强连通分量
模板:
#include<bits/stdc++.h> using namespace std; const int N=300002; map<string,int> a; int ver[N],next[N],head[N]; int dfn[N],low[N],s[N],ins[N],c[N]; int tot,cnt,idx,top; void add(int x,int y) { ver[++tot]=y; next[tot]=head[x]; head[x]=tot; } void tarjan(int x) { dfn[x]=low[x]=++idx; s[++top]=x; ins[x]=1; for(int i=head[x]; i; i=next[i]) { int y=ver[i]; if(dfn[y]==0) { tarjan(y); low[x]=min(low[y],low[x]); } else if(ins[y]) low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]) { cnt++; while(1) { c[s[top]]=cnt; ins[s[top]]=0; if(s[top--]==x) break; } } } int main() { int n,m ; scanf("%d",&n); string s1,s2; for(int i=1; i<=n ; i++) { cin>>s1>>s2; a[s1]=i; a[s2]=i+n; add(i,i+n); } scanf("%d",&m ); for(int i=1; i<=m ; i++) { cin>>s1>>s2; add(a[s2],a[s1]); } for(int i=1; i<=n*2; i++) { if(dfn[i]==0) tarjan(i); } for(int i=1; i<=n; i++) { if(c[i]==c[i+n]) puts("Unsafe"); else puts("Safe"); } return 0; }
DFS树
模板:
不讲
kosaraju算法求SCC
模板(核心):
inline void dfs(int k) { f[k]=0; for (int i=0;i<a[k].size();++i) if (f[a[k][i]]) dfs(a[k][i]); s.push_back(k); } inline void rdfs(int k) { f[k]=0; c[k]=tot; t[tot]++; for (int i=0;i<b[k].size();++i) if (f[b[k][i]]) rdfs(b[k][i]); }
tarjan算法求SCC
模板:
#include <bits/stdc++.h> using namespace std; const int maxn=10010; struct edge { int to; edge(int to_) { to=to_; } }; vector<edge> gpe[maxn]; int dfn[maxn],low[maxn],ins[maxn],scc[maxn],size[maxn],cnt=0,sccn=0; stack<int> s; void tarjan(int u) { dfn[u]=low[u]=++cnt; s.push(u); ins[u]=1; for(int i=0; i<gpe[u].size(); i++) { int v=gpe[u][i].to; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(ins[v]) { low[u]=min(low[u],dfn[v]); } } if(low[u]==dfn[u]) { ins[u]=0; scc[u]=++sccn; size[sccn]=1; while(s.top()!=u) { scc[s.top()]=sccn; ins[s.top()]=0; size[sccn]+=1; s.pop(); } s.pop(); } return; } int n,m,oud[maxn]; int main(void) { scanf("%d %d",&n,&m); memset(low,0x3f,sizeof(low)); memset(ins,0,sizeof(ins)); for(int i=1; i<=m; i++) { int u,v; scanf("%d %d",&u,&v); gpe[u].push_back(edge(v)); } for(int i=1; i<=n; i++) { if(!dfn[i]) { cnt=0; tarjan(i); } } for(int u=1; u<=n; u++) { for(int i=0; i<gpe[u].size(); i++) { int v=gpe[u][i].to; if(scc[u]!=scc[v]) oud[scc[u]]++; } } int cont=0,ans=0; for(int i=1; i<=sccn; i++) { if(oud[i]==0) { cont++; ans+=size[i]; } } if(cont==1) { printf("%d",ans); } else { printf("0"); } return 0; }
SAT问题
模板:
#include<bits/stdc++.h> #define LL long long LL in() { char ch; LL x = 0, f = 1; while(!isdigit(ch = getchar()))(ch == '-') && (f = -f); for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48)); return x * f; } const int maxn = 2e6 + 100; struct node { int to; node *nxt; node(int to = 0, node *nxt = NULL): to(to), nxt(nxt) {} void *operator new(size_t) { static node *S = NULL, *T = NULL; return (S == T) && (T = (S = new node[1024]) + 1024), S++; } }; node *head[maxn]; bool ins[maxn]; int st[maxn], top, bel[maxn], cnt, n, m, tot; int dfn[maxn], low[maxn]; void add(int from, int to) { head[from] = new node(to, head[from]); } void tarjan(int x) { dfn[x] = low[x] = ++tot; ins[st[++top] = x] = true; for(node *i = head[x]; i; i = i->nxt) { if(!dfn[i->to]) { tarjan(i->to); low[x] = std::min(low[x], low[i->to]); } else if(ins[i->to]) low[x] = std::min(low[x], dfn[i->to]); } if(dfn[x] == low[x]) { cnt++; do { bel[st[top]] = cnt; ins[st[top]] = false; top--; } while(st[top + 1] != x); } } bool judge() { for(int i = 1; i <= n; i++) printf("i = %d, bel = [%d,%d]\n", i, bel[i], bel[i + n]); for(int i = 1; i <= n; i++) if(bel[i] == bel[i + n]) return true; return false; } int main() { n = in(), m = in(); int x, y, xx, yy; for(int i = 1; i <= m; i++) { x = in(), xx = in(), y = in(), yy = in(); if(xx && yy) add(x + n, y), add(y + n, x); if(xx && !yy) add(x + n, y + n), add(y, x); if(!xx && yy) add(x, y), add(y + n, x + n); if(!xx && !yy) add(x, y + n), add(y, x + n); } for(int i = 1; i <= n << 1; i++) if(!dfn[i]) tarjan(i); if(judge()) printf("IMPOSSIBLE\n"); else { printf("POSSIBLE\n"); for(int i = 1; i <= n; i++) printf("%d%c", bel[i] < bel[i + n]? 1 : 0, i == n? '\n' : ' '); } return 0; }
再见