【图论基础模板】
//边链表 inline void insert(int u,int v,int w) { e[++cnt].to=v; e[cnt].next=head[u]; head[u]=cnt; e[cnt].v=w; } //vector vectot<int> G[M]; inline void insert(int u,int v) { G[u].push_back(v); G[v].push_back(u); } inline dfs(int x) { vis[x]=1; for(int i=0;i<G[x].size();i++) { int v=G[x][i]; if(!vis[v]) dfs(v); } } //遍历 inline dfs(int x,int fa) { vis[x]=1; for(int i=head[x];i;i=e[i].next) { if(e[i].to!=fa && !vis[e[i].to]) dfs(e[i].to,x); } } inline bfs(int s) { q.push(s); vis[s]=1; while(!q.empty()) { int now=q.front();q.pop(); for(int i=head[now];i;i=e[i].next) { if(!vis[e[i].to]) { q.push(e[i].to); vis[e[i].to]=1; } } } } //最短路 //floyd for(int k=1;k<=n;k++) for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) { if(f[i][j]>f[i][k]+f[k][j]) f[i][j]=f[i][k]+f[k][j]; } //dijkstra inline void dijkstra(int s) { priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > for(int i=0;i<=n;i++) dis[i]=inf; dis[s]=0;q.push(make_pair(dis[s],s); while(!q.empty()) { int now=q.top().second;q.pop(); if(vis[now]) continue; vis[now]=1; for(int i=head[now];i;i=e[i].next) if(dis[now]+e[i].v<dis[e[i].to]) { dis[e[i].to]=dis[now]+e[i].v; q.push(make_pair(dis[e[i].to],e[i].to)); } } } //spfa inline void spfa(int s) { queue<int> q; for(int i=1;i<=n;i++) dis[i]=inf; q.push(s); dis[s]=1; vis[s]=1; mark[s]++; while(!q.empty()) { int now=q.front();q.pop();vis[now]=0; for(int i=head[now];i;i=e[i].next) { if(dis[now]+e[i].v<dis[e[i].to]) { dis[e[i].to]=dis[now]+e[i].to; if(!vis[e[i].to]) { q.push(e[i].to); mark[e[i].to]++; if(mark[e[i].to]>=n) return -1;//有负环 vis[e[i].to]=1; } } } } } //并查集 inline int find(int x) { if(fa[x]==x) return x; else return fa[x]=find(fa[x]); } for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); int fx=find(x),fy=find(y); if(fx==fy) continue; fa[fx]=fy; } //kruskal inline bool cmp(node x,node y) { return x.v<y.v; } sort(a+1,a+m+1,cmp); for(int i=1;i<=m;i++) { int fx=find(a[i].x),fy=find(a[i].y); if(fx==fy) continue; fa[fx]=fy; ++cnt;ans+=a[i].v; if(cnt==n-1) break; } //topsort for(int i=1;i<=m;i++) { scanf("%d%d",&u,&v); d[v]++; } inline void topsort() { int tot=n; for(int i=1;i<=n;i++) { if(!d[i]) { q.push(i); tot--; t[++cnt]=i; } } while(!q.empty()) { int now=q.front();q.pop(); for(int i=head[now];i;i=e[i].next) { d[e[i].to]--; if(!d[e[i].to]) { q.push(e[i].to);tot--; t[++cnt]=e[i].to; } } } if(tot) return -1;//有负环 } //tarjan for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i); inline void tarjan(int x) { dfn[x]=low[x]=++time; s[++s[0]]=x; vis[x]=1; for(int i=head[x];i;i=e[i].next) { if(!dfn[e[i].to]) { tarjan(e[i].to); low[x]=min(low[x],low[e[i].to]); } else if(vis[e[i].to]) low[x]=min(low[x],dfn[e[i].to]); } if(dfn[x]==low[x]) { vis[now]=0;num[bl[now]=++scc]=1; while(s[s[0]]!=now) { vis[s[s[0]]]=0; bl[s[s[0]]]=scc; num[scc]++; s[0]--; } s[0]--; } } //割点 //u为割点 u->v //1.u为树根 且多于一个子树 2.low[v]>=dfn[u] //桥 //u->v 为桥 //low[v]>dfn[u] //lca(倍增) inline void dfs(int now,int fa) { for(int i=head[now];i;i=e[i].next) { if(e[i].to==fa) continue; dep[e[i].to]=dep[now]+1; f[e[i].to][0]=now; minn[e[i].to][0]=e[i].v; dfs(e[i].to,now); } } inline void st() { for(int i=1;i<=20;i++) for(int j=1;j<=n;j++) { f[j][i]=f[f[j][i-1]][i-1]; minn[j][i]=std::min(minn[j][i-1],minn[f[j][i-1]][i-1]); } } inline int lca(int u,int v) { if(dep[u]<dep[v]) swap(u,v); for(int i=20;i>=0;i--) if(dep[f[u][i]]>=dep[v]) u=f[u][i]; if(u==v) return u; for(int i=20;i>=0;i--) if(f[u][i]!=f[v][i]) u=f[u][i],v=f[v][i]; return f[u][0]; } //lca(树链剖分) inline void dfs1(int now) { sz[now]++; for(int i=head[now];i;i=e[i].next) { if(dep[e[i].to]) continue; dep[e[i].to]=dep[now]+1; fa[e[i].to]=now; dfs1(e[i].to); sz[now]+=sz[e[i].to]; } } inline void dfs2(int now,int clain) { top[now]=clain; int mxsz=0,pos=0; for(int i=head[now];i;i=e[i].next) { if(fa[e[i].to]==now) continue; if(sz[e[i].to]>mxsz) { pos=e[i].to; mxsz=sz[e[i].to]; } } dfs2(pos,clain); for(int i=head[now];i;i=e[i].next) { if(e[i].to==pos || fa[e[i].to]==now) continue; dfs2(e[i].to,e[i].to); } } inline int lca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); x=fa[top[x]]; } return dep[x]<dep[y]?x:y; } //欧拉回路 int cnt=1; inline void insert(int u,int v) { insert1(u,v); insert1(v,u); } inline void dfs(int x) { for(int i=head[x];i;i=e[i].next) { if(!vis[i]) { vis[i]=vis[i^1]=1; dfs(e[i].to); } } s.push_back(x); } bool check() { for(int i=1;i<=n;i++) if(d[i]&1) return 0;//不是欧拉回路 return 1; } //差分约束系统 //x0+d<=x1 x0->x1 边权为d //x0+d>=x1 x1-d<=x0 x1->x0 边权为-d //x0+d=x1 建两条边 x0+d<=x1 x0+d>=x1