圖論基礎知識總結
阿新 • • 發佈:2019-03-16
dfs inline str bit int fine val cap bits
圖論基礎知識總結
前言
因為博主太菜,好多之前學過的圖論算法都要不記得了,於是開了這篇博文提醒自己要記得復習圖論。
代碼
#include<bits/stdc++.h> using namespace std; #define gc() getchar() inline int In(){ char c=gc(); int x=0,ft=1; for(;c<'0'||c>'9';c=gc()) if(c=='-') ft=-1; for(;c>='0'&&c<='9';c=gc()) x=x*10+c-'0'; return x*ft; } // get cut vertex and bridge void dfs(int u,int fa){ dfn[u]=low[u]=++dfs_clock; int child=0; for(int i=h[u],v;i;i=e[i].nex){ v=e[i].to; if(!dfn[v]){ dfs(v,u); ++child; low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]) iscut[u]=1; if(low[v]>dfn[u]) // this edge is bridge } else if(v!=fa) low[u]=min(low[u],dfn[v]); } if(fa<0&&child==1) iscut[u]=0; } // get scc void tarjan(int u){ dfn[u]=low[u]=++dfs_clock; S[++S_top]=u; ins[u]=1; for(int i=h[u],v;i;i=e[i].nex){ v=e[i].to; if(!dfn[v]){ tarjan(v,u); low[u]=min(low[u],low[v]); } else if(ins[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]){ int v; ++I_cntl do{ v=S[S_top--]; id[v]=I_cnt; ins[v]=0; }while(v!=u); } } // get bcc // the bccno of the cut vertex is meaningless void dfs(int u,int fa){ low[u]=dfn[u]=++dfs_clock; int child=0; for(int i=h[u],v;i;i=e[i].nex){ v=e[i].to; Satus e=(Satus){u,v}; if(!dfn[v]){ S.push(e); ++child; dfs(v,u); low[u]=min(low[u],low[v]); if(low[v]>=dfn[u]){ iscut[u]=1; ++bcc_cnt; bcc[bcc_cnt].clear(); for(;;){ Satus x=S.top(); S.pop(); if(bccno[x.u]!=bcc_cnt){ bcc[bcc_cnt].push_back(x.u); bccno[x.u]=bcc_cnt; } if(bccno[x.v]!=bcc_cnt){ bcc[bcc_cnt].push_back(x.v); bccno[x.v]=bcc_cnt; } if(x.u==u&&x.v==v) break; } } else if(dfn[v]<dfn[u]&&v!=fa){ S.push(e); low[u]=min(low[u],dfn[v]); } } } if(fa<0&&child==1) iscut[u]=0; } void find_bcc(){ memset(dfn,0,sizeof(dfn)); memset(iscut,0,sizeof(iscut)); memset(bccno,0,sizeof(bccno)); dfs_clock=bcc_cnt=0; for(int i=1;i<=n;++i) if(!dfn[i]) dfs(i,-1); } // how to get ecc: 1.do dfs1 to get the bridge // 2.do dfs2 that don't pass the bridge // Two_sat namespace Twosat{ vector<int> G[N<<1]; bool mark[N<<1]; int S[N<<1],S_top; inline void init(){ for(int i=0;i<2*n;++i) G[i].clear(); memset(mark,0,sizeof(mark)); } bool dfs(int x){ if(mark[x^1]) return false; if(mark[x]) return true; mark[x]=true; S[++S_top]=x; for(int i=0;i<G[x].size();++i) if(!dfs(G[x][i])) return false; return true; } // x = xval or y = yval void Add_clause(int x,int xval,int y,int yval){ x=x*2+xval; y=y*2+yval; G[x^1].push_back(y); G[y^1].push_bask(x); } bool Solve(){ for(int i=0;i<n*2;i+=2) if(!mark[i]&&!mark[i+1]){ S_top=0; if(!dfs(i)){ while(S_top>0) mark[S[S_top--]]=false; if(!dfs(i+1)) return false; } } return true; } } // Dijkstra void djikstra(int s){ priority_queue<Node> Q; for(int i=1;i<=n;++i) d[i]=INF,done[i]=0; d[s]=0; done[s]=1; Q.push((Node){s,0}); while(!Q.empty()){ Node x=Q.top(); Q.pop(); int u=x.u; if(done[u]) continue; done[u]=true; for(int i=h[u],v;i;i=e[i].nex){ v=e[i].to; if(d[v]>d[u]+e[i].w){ d[v]=d[u]+e[i].w; Q.push((Node){v,d[v]}); } } } } // SPFA : he has died... bool SPFA(int s){ queue<int> Q; memset(inq,0,sizeof(inq)); memset(cnt,0,sizeof(cnt)); for(int i=1;i<=n;++i) d[i]=INF; d[s]=0; Q.push(s); inq[s]=1; while(!Q.empty()){ int u=Q.front(); Q.pop(); inq[u]=0; for(int i=h[u],v;i;i=e[i].nex){ v=e[i].to; if(d[v]>d[u]+e[i].w){ d[v]=d[u]+e[i].w; if(!inq[v]){ Q.push(v); inq[v]=1; if(++cnt[v]>n) return true; } } } } return false; } // directed tree // if there isn' answer return -1 int Solve(){ int ans=0,cnt; while(1){ for(int i=1;i<=n;++i) _in[i]=INF; for(int i=1;i<=m;++i){ int u=e[i].u,v=e[i].v; if(u!=v&&e[i].w<_in[v]) _in[v]=e[i].w,pre[v]=u; } for(int i=1;i<=n;++i) if(i!=root&&_in[i]==INF) return -1; cnt=0; for(int i=1;i<=n;++i) id[i]=vis[i]=0; for(int i=1;i<=n;++i){ if(i==root) continue; ans+=_in[i]; int v=i; while(vis[v]!=i&&!id[v]&&v!=root){ vis[v]=i; v=pre[v]; } if(!id[v]&&v!=root){ id[v]=++cnt; for(int u=pre[v];u!=v;u=pre[u]) id[u]=cnt; } } if(cnt==0) break; for(int i=1;i<=n;++i) if(!id[i]) id[i]=++cnt; for(int i=1;i<=m;++i){ int u=e[i].u,v=e[i].v; e[i].u=id[u]; e[i].v=id[v]; if(id[u]!=id[v]) e[i].w-=_in[v]; } root=id[root]; n=cnt; } return ans; } // Kruskal: insert the edge in the order that from min_w to max_w // Prim: each times find the best point to add into the tree // Dinic namespace Dinic{ int h[N],e_tot=0; struct E{ int to,nex,cap,flow; }e[M<<1]; inline void add(int u,int v,int w){ e[++e_tot]=(E){v,h[u],w,0}; h[u]=e_tot; } inline void Add(int u,int v,int w){ add(u,v,w); add(v,u,0); } inline void bool bfs(){ for(int i=s;i<=t;++i) cur[i]=h[i],vis[i]=0; queue<int> Q; Q.push(s); d[s]=0; vis[s]=1; while(!Q.empty()){ int u=Q.front(); Q.pop(); for(int i=h[u],v;i;i=e[i].nex){ v=e[i].to; if(!vis[v]&&e[i].cap-e[i].flow>0){ Q.push(v); d[v]=d[u]+1; vis[v]=1; } } } return vis[t]; } int dfs(int u,int las){ if(u==t||las==0) return las; int flow=0,f; for(int i=h[u],v;i;i=e[i].nex){ v=e[i].to; if(d[v]==d[u]+1&&(f=dfs(v,min(las,e[i].cap-e[i].flow)))>0){ e[i].flow+=f; e[i^1]-=flow; las-=f; flow+=f; if(!las) break; } } return flow; } inline int max_flow(){ int flow=0; while(bfs()) flow+=dfs(s,INF); return flow; } } int main(){ return 0; }
圖論基礎知識總結