『干货图论模板』

Parsnip·2019-02-18 20:20·194 次阅读

『干货图论模板』

<更新提示>

<第一次更新>这是一篇记录图论模板的博客


<正文>

最短路篇#

Dijkstra#

Copy
#include<bits/stdc++.h> using namespace std; const int N=500000,M=1000000; struct node { int index,val; bool operator <(const node temp)const { return this->val<temp.val; } bool operator >(const node temp)const { return this->val>temp.val; } }; struct edge { int ver,val,next; }e[M*2]; int n,m,dis[N],vis[N],Last[M*2],t,begin; inline void insert(int x,int y,int v) { e[++t].ver=y;e[t].val=v;e[t].next=Last[x];Last[x]=t; } inline void dijkstra(void) { memset(vis,0x00,sizeof vis); memset(dis,0x3f,sizeof dis); priority_queue< node,vector< node >,greater< node > > Heap; Heap.push((node){begin,0}); dis[begin]=0; while(!Heap.empty()) { int temp=Heap.top().index; Heap.pop(); if(vis[temp])continue; vis[temp]=true; for(int i=Last[temp];i;i=e[i].next) { int ver=e[i].ver; if(dis[ver]>dis[temp]+e[i].val) { dis[ver]=dis[temp]+e[i].val; Heap.push((node){ver,dis[ver]}); } } } } int main(void) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y,v; scanf("%d%d%d",&x,&y,&v); insert(x,y,v); insert(y,x,v); } scanf("%d",&begin); dijkstra(); for(int i=1;i<=n;i++) printf("The distence from %d to %d is %d\n",begin,i,dis[i]); return 0; }

SPFA#

Copy
#include<bits/stdc++.h> using namespace std; const int N=500000,M=1000000; struct edge { int ver,val,next; }e[M*2]; int n,m,dis[N],vis[N],Last[M*2],t,begin; inline void insert(int x,int y,int v) { e[++t].ver=y;e[t].val=v;e[t].next=Last[x];Last[x]=t; } inline void spfa(void) { memset(vis,0x00,sizeof vis); memset(dis,0x3f,sizeof dis); queue < int > q; dis[begin]=0;vis[begin]=true; q.push(begin); while(!q.empty()) { int temp=q.front(); q.pop(); vis[temp]=false; for(int i=Last[temp];i;i=e[i].next) { int ver=e[i].ver; if(dis[ver]>dis[temp]+e[i].val) { dis[ver]=dis[temp]+e[i].val; if(!vis[ver]) { q.push(ver); vis[ver]=true; } } } } } int main(void) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y,v; scanf("%d%d%d",&x,&y,&v); insert(x,y,v); insert(y,x,v); } scanf("%d",&begin); spfa(); for(int i=1;i<=n;i++) printf("The distence from %d to %d is %d\n",begin,i,dis[i]); return 0; }

最小生成树篇#

Prim#

Copy
#include<bits/stdc++.h> using namespace std; const int N=500000,M=1000000; struct node { int index,val; bool operator <(const node temp)const { return this->val<temp.val; } bool operator >(const node temp)const { return this->val>temp.val; } }; struct edge { int ver,val,next; }e[M*2]; int n,m,dis[N],vis[N],Last[M*2],t,ans; inline void insert(int x,int y,int v) { e[++t].ver=y;e[t].val=v;e[t].next=Last[x];Last[x]=t; } inline void prim(void) { memset(vis,0x00,sizeof vis); memset(dis,0x3f,sizeof dis); priority_queue< node,vector< node >,greater< node > > Heap; Heap.push((node){1,0}); dis[1]=0; while(!Heap.empty()) { node temp=Heap.top(); Heap.pop(); if(vis[temp.index])continue; vis[temp.index]=true; ans+=temp.val; int T=temp.index; for(int i=Last[T];i;i=e[i].next) { int ver=e[i].ver; if(dis[ver]>e[i].val) { dis[ver]=e[i].val; Heap.push((node){ver,dis[ver]}); } } } } int main(void) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y,v; scanf("%d%d%d",&x,&y,&v); insert(x,y,v); insert(y,x,v); } prim(); printf("%d\n",ans); return 0; }

Kruscal#

Copy
#include<bits/stdc++.h> using namespace std; const int N=500000,M=1000000; struct Link{int x,y,val;}e[M]; int n,m,ans,f[N]; inline bool cmp(Link p1,Link p2){return p1.val<p2.val;} inline int find(int x){return f[x]==x?x:f[x]=find(f[x]);} inline void kruscal(void) { int cnt=0; for(int i=1;i<=n;i++) f[i]=i; sort(e+1,e+m+1,cmp); for(int i=1;i<=m;i++) { int x=find(e[i].x),y=find(e[i].y); if(x==y)continue; f[x]=y; ans+=e[i].val; if(++cnt==n-1)break; } } int main(void) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].val); kruscal(); printf("%d\n",ans); return 0; }

树上问题篇#

LCA#

Copy
#include<cstdio> #include<cstring> #include<iostream> #define mset(name,val) memset(name,val,sizeof name) using namespace std; const int N=30000+20,MaxlogN=30; int n,Last[N],t,askx,asky,depth[N],f[N][MaxlogN],root=0,vis[N]; struct edge{int ver,next;}e[N]; inline void insert(int x,int y) { e[++t].ver=y;e[t].next=Last[x];Last[x]=t; } inline void input(void) { scanf("%d",&n); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); insert(x,y); vis[y]=1; } scanf("%d%d",&askx,&asky); for(int i=1;i<=n;i++) { if(!vis[i]) { root=i; break; } } } inline void init(int x,int dep) { depth[x]=dep; for(int i=Last[x];i;i=e[i].next) { int y=e[i].ver; if(f[x][0]==y)continue; f[y][0]=x; init(y,dep+1); } } inline void dp(void) { f[root][0]=-1; for(int k=1;(1<<k)<n;k++) { for(int i=1;i<=n;i++) { if(f[i][k-1]<0)f[i][k]=-1; else f[i][k]=f[f[i][k-1]][k-1]; } } } inline int LCA(int x,int y) { if(depth[x]>depth[y])x^=y^=x^=y; for(int d=depth[y]-depth[x],i=0;d;d>>=1,i++) if(d&1)y=f[y][i]; if(x==y)return x; for(int i=MaxlogN-1;i>=0;i--) { if(f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } } return f[x][0]; } inline void reset(void) { mset(Last,0); mset(e,0); mset(depth,0); mset(f,0); mset(vis,0); t=0; } signed main(void) { int T; scanf("%d",&T); while(T--) { reset(); input(); init(root,0); dp(); printf("%d\n",LCA(askx,asky)); } return 0; }

树的直径BFS#

Copy
#include<cstdio> #include<iostream> #include<queue> #include<vector> #include<cstring> #define mset(name,val) memset(name,val,sizeof name) using namespace std; const int N=40000+50; int n,m,ans,vis[N],dis[N]; struct edge{int val,ver;}; vector < edge > Link[N]; inline void input(void) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y,v; scanf("%d%d%d",&x,&y,&v); Link[x].push_back((edge){v,y}); Link[y].push_back((edge){v,x}); } } inline int Search(int start) { queue< int >q; mset(vis,0x00); mset(dis,0x00); vis[start]=1; q.push(start); while(!q.empty()) { int temp=q.front();q.pop(); for(int i=0;i<Link[temp].size();i++) { if(!vis[Link[temp][i].ver]) { vis[Link[temp][i].ver]=true; dis[Link[temp][i].ver]=dis[temp]+Link[temp][i].val; q.push(Link[temp][i].ver); } } } int res=0,Maxdis=0; for(int i=1;i<=n;i++) { if(dis[i]>Maxdis) { Maxdis=dis[i]; res=i; } } return res; } int main(void) { input(); int p=Search(1); printf("%d\n",dis[Search(p)]); return 0; }

树的直径DP#

Copy
#include<cstdio> #include<iostream> #include<vector> #include<cstring> #define mset(name,val) memset(name,val,sizeof name) using namespace std; const int N=40000+50; int n,m,ans,vis[N],d[N],f[N]; struct edge{int val,ver;}; vector < edge > Link[N]; inline void input(void) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y,v; scanf("%d%d%d",&x,&y,&v); Link[x].push_back((edge){v,y}); Link[y].push_back((edge){v,x}); } } inline int dp(int x) { vis[x]=true; for(int i=0;i<Link[x].size();i++) { int y=Link[x][i].ver; if(!vis[y]) { dp(y); f[x]=max(f[x],d[x]+d[y]+Link[x][i].val); d[x]=max(d[x],d[y]+Link[x][i].val); } } ans=max(ans,f[x]); } int main(void) { input(); dp(1); printf("%d\n",ans); return 0; }

树的重心#

Copy
#include<cstdio> #include<iostream> #include<queue> #include<vector> #include<cstring> #define mset(name,val) memset(name,val,sizeof name) using namespace std; const int N=20000+50; int n,size[N],Max[N],ans,cnt; vector < int > Link[N]; inline void input(void) { scanf("%d",&n); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); Link[x].push_back(y); Link[y].push_back(x); } } inline void dp(int r,int f) { size[r]=1; for(int i=0;i<Link[r].size();i++) { int Son=Link[r][i]; if(Son==f)continue; dp(Son,r); size[r]+=size[Son]; Max[r]=max(Max[r],size[Son]); } Max[r]=max(Max[r],n-size[r]); if(Max[r]==Max[ans]&&r<ans)ans=r; if(Max[r]<Max[ans])ans=r; } int main(void) { Max[0]=0x3f3f3f3f; input(); dp(1,0); printf("%d\n",ans); }

树上差分(点)#

Copy
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int N=100000+200,K=200000+200,MaxlogN=30; int n,k,cnt[N],depth[N],Last[N*2],t,f[N][MaxlogN],ans=0; struct edge{int ver,next;}e[N*2]; inline void insert(int x,int y) { e[++t].ver=y;e[t].next=Last[x];Last[x]=t; } inline void input(void) { scanf("%d%d",&n,&k); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); insert(x,y); insert(y,x); } } inline void init(int x,int dep) { depth[x]=dep; for(int i=Last[x];i;i=e[i].next) { int y=e[i].ver; if(f[x][0]==y)continue; f[y][0]=x; init(y,dep+1); } } inline void dp(void) { f[1][0]=-1; for(int k=1;(1<<k)<n;k++) { for(int i=1;i<=n;i++) { if(f[i][k-1]<0)f[i][k]=-1; else f[i][k]=f[f[i][k-1]][k-1]; } } } inline int LCA(int x,int y) { if(depth[x]>depth[y]) x^=y^=x^=y; for(int d=depth[y]-depth[x],i=0;d;d>>=1,i++) if(1&d)y=f[y][i]; if(x==y)return x; for(int i=MaxlogN-1;i>=0;i--) { if(f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } } return f[x][0]; } inline void Mark(void) { for(int i=1;i<=k;i++) { int x,y; scanf("%d%d",&x,&y); cnt[x]++;cnt[y]++; int lca=LCA(x,y); cnt[lca]--; if(lca!=1)cnt[f[lca][0]]--; } } inline void Get_sum(int r) { for(int i=Last[r];i;i=e[i].next) { int Son=e[i].ver; if(Son==f[r][0])continue; Get_sum(Son); cnt[r]+=cnt[Son]; } ans=max(ans,cnt[r]); } signed main(void) { input(); init(1,0); dp(); Mark(); Get_sum(1); printf("%d\n",ans); return 0; }

树上差分(边)#

Copy
#include<cstdio> #include<cstring> #include<iostream> using namespace std; const int N=100000+200,K=200000+200,MaxlogN=30; int n,k,cnt[N],depth[N],Last[N*2],t,f[N][MaxlogN],ans=0; struct edge{int ver,next;}e[N*2]; inline void insert(int x,int y) { e[++t].ver=y;e[t].next=Last[x];Last[x]=t; } inline void input(void) { scanf("%d%d",&n,&k); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); insert(x,y); insert(y,x); } } inline void init(int x,int dep) { depth[x]=dep; for(int i=Last[x];i;i=e[i].next) { int y=e[i].ver; if(f[x][0]==y)continue; f[y][0]=x; init(y,dep+1); } } inline void dp(void) { f[1][0]=-1; for(int k=1;(1<<k)<n;k++) { for(int i=1;i<=n;i++) { if(f[i][k-1]<0)f[i][k]=-1; else f[i][k]=f[f[i][k-1]][k-1]; } } } inline int LCA(int x,int y) { if(depth[x]>depth[y]) x^=y^=x^=y; for(int d=depth[y]-depth[x],i=0;d;d>>=1,i++) if(1&d)y=f[y][i]; if(x==y)return x; for(int i=MaxlogN-1;i>=0;i--) { if(f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } } return f[x][0]; } inline void Mark(void) { for(int i=1;i<=k;i++) { int x,y; scanf("%d%d",&x,&y); cnt[x]++;cnt[y]++; int lca=LCA(x,y); cnt[lca]-=2; } } inline void Get_sum(int r) { for(int i=Last[r];i;i=e[i].next) { int Son=e[i].ver; if(Son==f[r][0])continue; Get_sum(Son); cnt[r]+=cnt[Son]; } ans=max(ans,cnt[r]); } signed main(void) { input(); init(1,0); dp(); Mark(); Get_sum(1); printf("%d\n",ans); return 0; }

图的连通性篇#

Tarjan割点#

Copy
#include<bits/stdc++.h> using namespace std; const int N=90000,M=150000; int n,Last[M],t,cutvertex[N],dfn[N],low[N],cnt,m,ans[N],tot; struct edge{int ver,next;}e[M]; inline void insert(int x,int y) { e[++t].ver=y;e[t].next=Last[x];Last[x]=t; } inline void input(void) { scanf("%d%d",&n,&m); int x,y; for(int i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(x^y)insert(x,y),insert(y,x); } } inline void Tarjan(int x,int root) { dfn[x]=low[x]=++cnt; int flag=0; for(int i=Last[x];i;i=e[i].next) { int y=e[i].ver; if(!dfn[y]) { Tarjan(y,root); low[x]=min(low[x],low[y]); if(low[y]>=dfn[x]) { flag++; if(x!=root||flag>1)cutvertex[x]=true; } } else low[x]=min(low[x],dfn[y]); } } int main(void) { input(); for(int i=1;i<=n;i++) if(!dfn[i])Tarjan(i,i); for(int i=1;i<=n;i++) { if(cutvertex[i]) ans[++tot]=i; } if(tot)printf("%d\n",tot); else printf("0\n"); for(int i=1;i<=tot;i++) printf("%d\n",ans[i]); }

Tarjan割边#

Copy
#include<bits/stdc++.h> using namespace std; const int N=100000+200,M=300000+200; int n,m,t=1,Last[M*2],dfn[N],low[N],bridge[N],cnt,tot; struct edge{int ver,next;}e[M*2]; pair < int,int > ans[N]; inline void insert(int x,int y) { e[++t].ver=y;e[t].next=Last[x];Last[x]=t; } inline void input(void) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); insert(x,y); insert(y,x); } } inline void Tarjan(int x,int inedge) { dfn[x]=low[x]=++cnt; for(int i=Last[x];i;i=e[i].next) { int y=e[i].ver; if(!dfn[y]) { Tarjan(y,i); low[x]=min(low[x],low[y]); if(low[y]>dfn[x]) bridge[i]=bridge[i^1]=true; } else if(i!=(inedge^1)) low[x]=min(low[x],dfn[y]); } } int main(void) { input(); for(int i=1;i<=n;i++) if(!dfn[i])Tarjan(i,0); for(int i=2;i<t;i+=2) if(bridge[i]) { if(e[i].ver>e[i^1].ver)swap(e[i].ver,e[i^1].ver); ans[++tot]=make_pair(e[i].ver,e[i^1].ver); } sort(ans+1,ans+tot+1); for(int i=1;i<=tot;i++) printf("%d %d\n",ans[i].first,ans[i].second); return 0; }

Tarjan强连通分量#

Copy
#include<bits/stdc++.h> using namespace std; const int N=20000+200,M=80000+200; int n,m,dfn[N],low[N],cnt,Last[M*2],t,inSta[N],size[N],tot; stack < int > Stack; struct edge{int ver,next;}e[M*2]; struct connected { int len=0; vector < int > List; }con[N]; inline bool cmp(connected p1,connected p2) { return p1.len>p2.len; } inline void insert(int x,int y) { e[++t].ver=y;e[t].next=Last[x];Last[x]=t; } inline void input(void) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int a,b,t; scanf("%d%d%d",&a,&b,&t); if(t==1)insert(a,b); else insert(a,b),insert(b,a); } } inline void Tarjan(int x) { dfn[x]=low[x]=++cnt; Stack.push(x);inSta[x]=true; for(int i=Last[x];i;i=e[i].next) { int y=e[i].ver; if(!dfn[y]) { Tarjan(y); low[x]=min(low[x],low[y]); } else if(inSta[y])low[x]=min(low[x],dfn[y]); } if(low[x]==dfn[x]) { int top=0;tot++; while(top!=x) { top=Stack.top(); Stack.pop(); con[tot].len++; con[tot].List.push_back(top); inSta[top]=false; } } } inline void print(void) { sort(con[1].List.begin(),con[1].List.end()); int T=1,best=1,l=con[1].len; for(int i=2;i<=tot;i++) { if(con[i].len==con[i-1].len) { sort(con[i].List.begin(),con[i].List.end()); T++; } else break; } for(int i=2;i<=T;i++) { for(int j=0;j<l;j++) { if(con[i].List[j]<con[best].List[j]) { best=i; break; } else if(con[i].List[j]>con[best].List[j]) break; } } for(int i=0;i<l-1;i++) printf("%d ",con[best].List[i]); printf("%d\n",con[best].List[l-1]); } int main(void) { input(); for(int i=1;i<=n;i++) if(!dfn[i])Tarjan(i); sort(con+1,con+tot+1,cmp); printf("%d\n",con[1].len); print(); return 0; }

Tarjan点双连通分量#

Copy
#include<bits/stdc++.h> using namespace std; const int M=500*3,N=1000; int m,n,Last[N],t,dfn[N],low[N],cnt,T; long long ans1,ans2=1; struct edge{int ver,next;}e[M]; vector < int >con[N]; stack < int > Stack; inline void insert(int x,int y) { e[++t].ver=y;e[t].next=Last[x];Last[x]=t; } inline bool input(void) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); insert(x,y); insert(y,x); } return true; } inline void Tarjan(int x,int root) { dfn[x]=low[x]=++cnt; Stack.push(x); if(x==root&&!Last[x]) { Stack.pop();T++; con[T].push_back(x); return; } for(int i=Last[x];i;i=e[i].next) { int y=e[i].ver; if(!dfn[y]) { Tarjan(y,root); low[x]=min(low[x],low[y]); if(low[y]>=dfn[x]) { int top=0;T++; while(top!=y) { top=Stack.top(); Stack.pop(); con[T].push_back(top); } con[T].push_back(x); } } else low[x]=min(low[x],dfn[y]); } } int main(void) { input(); Tarjan(1,1); for(int i=1;i<=T;i++) { printf("The vertex biconnected component #%d :",i); for(int j=0;j<con[i].size();j++) printf("%d ",con[i][j]); puts(""); } return 0; }

Tarjan边双连通分量#

Copy
#include<bits/stdc++.h> using namespace std; const int N=10000,M=40000; int n,m,Last[M],dfn[N],low[N],cnt,con[N],t=1,tot; struct edge{int ver,next,flag;}e[M]; inline void insert(int x,int y) { e[++t].ver=y;e[t].next=Last[x];Last[x]=t; } inline void input(void) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); insert(x,y); insert(y,x); } } inline void Tarjan(int x,int inedge) { dfn[x]=low[x]=++cnt; for(int i=Last[x];i;i=e[i].next) { int y=e[i].ver; if(!dfn[y]) { Tarjan(y,i); low[x]=min(low[x],low[y]); if(low[y]>dfn[x])e[i].flag=e[i^1].flag=true; } else if(i!=(inedge^1))low[x]=min(low[x],dfn[y]); } } inline void dfs(int x) { con[x]=tot; printf("%d ",x); for(int i=Last[x];i;i=e[i].next) { if(e[i].flag)continue; int y=e[i].ver; if(!con[y])dfs(y); } } inline void colored(void) { for(int i=1;i<=n;i++) if(!con[i]) { ++tot; printf("The Edge biconnected component #%d :",tot); dfs(i); puts(""); } } int main() { input(); Tarjan(1,0); colored(); return 0; }

判环篇#

Topsort#

Copy
#include<bits/stdc++.h> using namespace std; const int N=500000,M=1000000; struct edge { int ver,next; }e[M*2]; int n,m,Last[M*2],t,loop,indeg[N],cnt,ans[N]; queue < int > q; inline void insert(int x,int y) { e[++t].ver=y;e[t].next=Last[x];Last[x]=t; } inline bool topsort(void) { for(int i=1;i<=n;i++) if(!indeg[i])q.push(i); while(!q.empty()) { int temp=q.front();q.pop();ans[++cnt]=temp; for(int i=Last[temp];i;i=e[i].next) { int ver=e[i].ver; indeg[ver]--; if(!indeg[ver])q.push(ver); } } return cnt==n; } int main(void) { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); insert(x,y); indeg[y]++; } topsort(); if(loop)printf("Impossible\n"); else for(int i=1;i<=n;i++) printf("%d ",ans[i]); puts(""); return 0; }

<后记>

posted @   Parsnip  阅读(194)  评论(0编辑  收藏  举报
编辑推荐:
· .NET制作智能桌面机器人:结合BotSharp智能体框架开发语音交互
· 软件产品开发中常见的10个问题及处理方法
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
阅读排行:
· 《HelloGitHub》第 108 期
· Windows桌面应用自动更新解决方案SharpUpdater5发布
· 我的家庭实验室服务器集群硬件清单
· Supergateway:MCP服务器的远程调试与集成工具
· C# 13 中的新增功能实操
点击右上角即可分享
微信分享提示
目录