图论模板收录

这里主要收录一些与图论有关的模板

 啊我还是太弱了居然要收录模板 

 

1.链式向前星

 1 //链式向前星(数组模拟邻接表)
 2 //单向链表 
 3 struct pp
 4 {
 5     int s;//开始 (父亲) 
 6     int e;//结束 (儿子) 
 7     int v;//权值 
 8     int nex;
 9  } f[maxn];
10  int fir[maxn];
11 int main()
12 {
13     scanf("%d",&n);
14     for(int i=1;i<=n;i++)//n条边 
15     {
16         scanf("%d",x,y,z);
17         f[i].s=x;
18         f[i].e=y;
19         f[i].v=z;
20         f[i].nex=fir[x];
21         fir[x]=i;
22     }
23     for(int i=fir[f];i;i=f[i].nex)
24         dfs;//遍历 
25 }
26 
27 //双向链表 
28 struct pp
29 {
30     int s;//开始 (父亲) 
31     int e;//结束 (儿子) 
32     int v;//权值 
33     int nex;
34  } f[maxn*2];
35  int fir[maxn];
36  int tot=0;
37  void build(int x,int y,int z) 
38 {
39     f[++tot].e=y; 
40     f[tot].s=x; 
41     f[tot].nex=fir[x];
42     f[tot].v=z;
43     fir[x]=tot;
44 }
45 //遍历,每个边遍历两次
46 int main()
47 {
48     scanf("%d",&n);//n条边 
49      for(int i=1;i<=n;i++)
50     {
51         int x,y,z;  scanf("%d%d%d",&x,&y,&z);
52         build(x,y,z); build(y,x,z);//来回时边权相同,不同的话循环n*2次依次输入 
53     }
54     for(int i=fir[f];i;i=f[i].nex)
55         dfs;
56      
57  } 
58  //树的遍历 ,只遍历一次(n个结点,n-1条边的全连通图叫树) 
59  void dfsl(int f,int fath)//现在的位置,父亲 
60 {
61     for(int i=fir[f];i;i=f[i].nex)
62       if(f[i].t!=fath)//遍历儿子结点并DFS 
63         dfsl(f[i].t,f);
64 }
65 int mian()
66 {
67     scanf("%d%d",&n,&s);//n个结点,s为根 
68     for(int i=1;i<=n-1;i++)
69     {
70         int x,y;  scanf("%d%d",&x,&y);
71         build(x,y); build(y,x);
72     }
73     dfsl(s,0);
74 }
链式向前星

 

2.LCA

LCA
 1 //LCA 
 2 #include
 3 #include
 4 #include
 5 #include
 6 #include
 7 using namespace std;
 8 const int maxn=500050;
 9 int tot,n,m,s;
10 struct pp
11 {
12     int t;
13     int nex;
14 }u[maxn*2];//邻接表(链式向前星)建图 
15 int fir[maxn],lg[maxn],fa[500001][22],dep[maxn];//邻接表(链式向前星)头数组,预处理 log_2(i)+1的值,fa[x][j]表示x的第2^j个祖先,深度 
16 void dfs(int f,int fath)//现在的位置,父亲 
17 {
18     dep[f]=dep[fath]+1;
19     fa[f][0]=fath;
20     for(int i=1;(1<) 
21       fa[f][i]=fa[fa[f][i-1]][i-1];//他的第2^i个祖先是他第2^(i-1)个祖先的第 2^(i-1)个祖先
22     for(int i=fir[f];i;i=u[i].nex)
23       if(u[i].t!=fath)//遍历儿子结点并DFS 
24         dfs(u[i].t,f);
25 }
26 int lca(int x,int y)
27 {
28     if(dep[x]//不妨假设x的深度更深 
29       swap(x,y);
30     while(dep[x]>dep[y])
31       x=fa[x][lg[dep[x]-dep[y]]-1];//先跳到同一高度 
32     if(x==y)
33       return x;
34     for(int k=lg[dep[x]]-1;k>=0;k--)
35       if(fa[x][k]!=fa[y][k])
36         x=fa[x][k], y=fa[y][k];//跳的LCA的儿子节点上 
37     return fa[x][0];//返回LCA 
38 }
39 void build(int x,int y) 
40 {
41     u[++tot].t=y; 
42     u[tot].nex=fir[x];
43     fir[x]=tot;
44 }
45 int main()
46 {
47     scanf("%d%d%d",&n,&m,&s);//n个结点,m次询问,s为根 
48     for(int i=1;i<=n-1;i++)
49     {
50         int x,y;  scanf("%d%d",&x,&y);
51         build(x,y); build(y,x);
52     }
53     dfs(s,0);
54 
55     for(int i=1;i<=n;i++)
56       lg[i]=lg[i-1]+(1<1]==i);//预处理,计算log_2(i)+1的值,用于优化常数 
57     for(int i=1;i<=m;i++)
58     {
59         int x,y;  scanf("%d%d",&x,&y);
60         printf("%d\n",lca(x,y));
61     }
62     return 0;
63 }

 

3.Kruskal求最小生成树

 1 #include
 2 #include 
 3 #include
 4 using namespace std;
 5 int n,k,t,ans,cnt,res,m;
 6 struct pp
 7 {
 8     int u;
 9     int v;
10     int w;
11 }s[2000002];
12 int f[2000002],h[2000002];
13 int gf(int x)
14 {
15     if(f[x]==x) return x;
16     return f[x]=gf(f[x]);
17 }
18 bool cmp(pp x,pp y)
19 {
20     return x.w<y.w;
21 }
22 bool solve(int x,int y)
23 {
24     int t1=gf(x);int t2=gf(y);
25     if(t1!=t2)
26     {
27         f[t2]=t1;
28         return true;
29     }
30     return false;
31 }
32 int main()
33 {
34     scanf("%d%d",&n,&m);
35     for(int i=1;i<=n;i++)
36         f[i]=i;
37     for(int i=1;i<=m;i++)
38         scanf("%d%d%d",&s[i].u,&s[i].v,&s[i].w);
39     sort(s+1,s+1+m,cmp);
40     for(int i=1;i<=m;i++)
41     {
42         if(solve(s[i].u,s[i].v))
43         {
44             res++;
45             ans+=(res,s[i].w);//最小生成树的路径之和 
46         }
47         if(res==(n-1))
48         break;
49     }
50     cout<<ans;
51     return 0;
52 }
Kruskal

 

4.Floyd求任意两点最短路

 1 for(int i=1;i<=n;i++)
 2   for(int j=1;j<=n;j++)
 3     f[i][j]=INF;
 4 for(int i=1;i<=n;i++)
 5     f[i][i]=0;
 6 for( int k=1;k<=n;k++)
 7       for(int i=1;i<=n;i++)
 8         for( int j=1;j<=n;j++)
 9           if(f[i][k]+f[k][j]<f[i][j])
10              f[i][j]=f[i][k]+f[k][j];
Floyd

 

5.DIS分层图

数组开二维更好写一些~

而且好确定范围

#include
#include
#include
#include
#include
#include
using namespace std;
const int M=1000200;
int n,m,t,res,ans,cnt,num,k,root,end;
int head[M];
int dis[M],vis[M];
struct node{
    int dis;
    int pos;
    bool operator <(const node &x) const{
        return dis>x.dis;
    }
}s[M];
priority_queue  q;
struct pp{
    int u;
    int v;
    int nex;
}e[5*M];

void add(int x,int y,int z){
    e[++cnt].u=y;
    e[cnt].v=z;
    e[cnt].nex=head[x];
    head[x]=cnt;
}
void di(){
    dis[root]=0;
    q.push((node){0,root});
    while(!q.empty()){
        node tmp=q.top();
        q.pop();
        int x=tmp.pos;
        int d=tmp.dis;
        if(vis[x]) continue;
        vis[x]=1;
        for(int i=head[x];i;i=e[i].nex){
            int y=e[i].u;
            if(dis[y]>dis[x]+e[i].v){
                dis[y]=e[i].v+dis[x];
                if(!vis[y])
                q.push((node){dis[y],y});
            }
        }
    }
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    scanf("%d%d",&root,&end);
    for(int i=1;i<=m;i++)
    {
        int aa,bb,cc,dd;
        scanf("%d%d%d",&aa,&bb,&cc);
        add(aa,bb,cc);add(bb,aa,cc);
        for(int j=1;j<=k;j++){
            add(n*j+aa,n*j+bb,cc);
            add(n*j+bb,n*j+aa,cc);
            add((j-1)*n+aa,j*n+bb,0);
            add((j-1)*n+bb,j*n+aa,0);
        }
    }
    memset(dis,0x3f,sizeof(dis));
    di();
    ans=dis[end];
    for(int i=1;i<=k;i++){
        ans=min(ans,dis[n*i+end]);
    }
    printf("%d",ans);
    return 0;
}
分层图

 

你可能感兴趣的:(图论模板收录)