【模板】其他图论

来源:互联网 发布:java分解质因数 编辑:程序博客网 时间:2024/06/05 20:29

LCA(暴力):

#include <iostream>#include <cstdio>#include <cstring>#include <queue>using namespace std;const int MAXN = 50000 + 50;int n, tot = 0, m;int first[MAXN], nxt[MAXN << 1], dis[MAXN], deep[MAXN], fa[MAXN];bool vis[MAXN];struct edge{    int from, to, cost;}es[MAXN << 1];void build(int ff, int tt, int dd){    es[++tot] = (edge){ff,tt,dd};    nxt[tot] = first[ff];    first[ff] = tot;}void dfs(int x){    for(int i = first[x]; i != -1; i = nxt[i])    {        int v = es[i].to;        if(!vis[v])        {            vis[v] = 1;            dis[v] = es[i].cost;            deep[v] = deep[x] + 1;            fa[v] = x;            dfs(v);        }    }}int lca(int x, int y){    int ans = 0;    if(deep[x] > deep[y])        swap(x,y);    while(deep[y] != deep[x])    {        ans += dis[y];        y = fa[y];    }    while(x != y)    {        ans += dis[x];        ans += dis[y];        x = fa[x];        y = fa[y];    }    return ans;}int main(){    scanf("%d",&n);    memset(first,-1,sizeof(first));    memset(dis,0x3f3f3f3f,sizeof(dis));    for(int i = 1; i < n; i ++)    {        fa[i] = i;        int f, t, d;        scanf("%d%d%d", &f, &t, &d);        build(f,t,d);        build(t,f,d);    }    deep[0] = 1;    vis[0] = 1;    dfs(0);     scanf("%d",&m);    while(m --)    {        scanf("%d%d", &f, &t);        printf("%d\n",lca(f,t));    }    return 0;}

LCA(倍增):

#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>using namespace std;const int SZ = 501000;struct edge{    int f,t;}es[SZ<<1];int tot = 0,first[SZ<<1],nxt[SZ<<1];int deep[SZ],anc[SZ][30];bool vis[SZ];void build(int f,int t){    es[++tot] = (edge){f,t};    nxt[tot] = first[f];    first[f] = tot;}void dfs(int u){    vis[u] = 1;    if(u == 0) deep[u] = 1;    for(int i = 1;i <= 16;i ++)        anc[u][i] = anc[anc[u][i-1]][i-1];    for(int i = first[u];i;i = nxt[i])    {        int v = es[i].t;        if(!vis[v])        {            anc[v][0] = u;            deep[v] = deep[u] + 1;            dfs(v);        }    }}int lca(int u,int v){    if(deep[u] < deep[v]) swap(u,v);    int tt = deep[u]-deep[v];    for(int i = 0;i <= 16;i ++)    {        if(tt & (1 << i))        u = anc[u][i];    }    for(int i = 16;i >= 0;i --)    if(anc[u][i] != anc[v][i])    {        u = anc[u][i];        v = anc[v][i];    }    if(u != v) return anc[u][0];    return u;}int main(){    int n,m,s;    scanf("%d%d%d",&n,&m,&s);    for(int i = 1;i < n;i ++)    {        int u,v;        scanf("%d%d",&u,&v);        build(u,v);        build(v,u);    }    dfs(s);    for(int i = 1;i <= m;i ++)    {        int u,v;        scanf("%d%d",&u,&v);        printf("%d\n",lca(u,v));    }    return 0;}

Tarjan:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<stack>using namespace std;const int maxn=100010;int scc[maxn],dfn[maxn];//强连通分量、第一次发现 int low[maxn];//某点及其后代能连到的最早值 int head[maxn],tot,cnt,ans[maxn];//scc总数 和 访问次数stack<int>s;struct Edge{    int to;    int fff;    int d;    int next;}edge[maxn];void build(int fff,int tt) {    edge[++tot].to=tt;    edge[tot].next=head[fff];    head[fff]=tot;}int dfs_clock=0;void tarjan(int u){    dfn[u]=low[u]=++dfs_clock;    s.push(u);    for(int i=head[u];i;i=edge[i].next)    {        Edge e=edge[i];        int v=e.to;        if(!dfn[v])        {            tarjan(v);            low[u]=min(low[u],low[v]);        }        else if(!scc[v])        {            low[u]=min(low[u],dfn[v]);        }    }    if(low[u]==dfn[u])    {        cnt++;        while(1)        {            int x=s.top();            s.pop();            scc[x] = cnt;            ans[scc[x]] = cnt2;            if(x == u)break;        }    }}

SPFA判负环:

ll spfa(ll s){    memset(dis,0x3f,sizeof(dis));    memset(vis,0,sizeof(vis));    memset(use,0,sizeof(use));    dis[s] = 0;    q.push(s);    vis[s] = 1;    use[s] = true;    while(!q.empty())    {        ll u = q.front();        q.pop();        use[u] = false;        if(vis[u] > n + 1) return -1;        for(ll i = first[u];i != -1;i = next[i])        {            ll v = l[i].t;            if(dis[v] > dis[u] + l[i].v)            {                dis[v] = dis[u] + l[i].v;                vis[v] = vis[u] + 1;                if(!use[v])                {                    q.push(v);                    use[v] = true;                }            }        }    }    return 0;}int main(){    init();     ll s,f,t,v;    scanf("%lld %lld %lld",&n,&m,&s);    for(ll i = 1;i <= m;i ++)    {        scanf("%lld %lld %lld",&f,&t,&v);        build(f,t,v);    }    for(ll i = 0;i <= n;i ++)    {        if(spfa(i) == -1)        {            puts("-1");            return 0;        }    }    spfa(s);    for(ll i = 1;i <= n;i ++)    if(dis[i] >= INF) puts("NoPath");    else printf("%lld\n",dis[i]);    return 0;}

严格次短路:

#include<iostream>#include<cstdio>#include<queue>#include<algorithm>#include<cstring>using namespace std;const int maxn = 2000000;struct Edge{    int from, to, cost;}es[maxn];int first[maxn], nxt[maxn] , tot = 0;long long zd[maxn], cd[maxn];bool used[maxn];queue < int > q;void build(int f, int t, int d){    es[++tot] = (Edge){f,t,d};    nxt[tot] = first[f];    first[f] = tot;}void spfa(int s){    zd[s] = 0;    q.push(s);    used[s] = 1;    while(!q.empty())    {        int u = q.front();        q.pop();        used[u] = 0;        for(int i = first[u]; i != -1; i = nxt[i])        {            int v = es[i].to;            if(zd[v] > zd[u] + es[i].cost)            {                cd[v] = zd[v];                zd[v] = zd[u] + es[i].cost;                if(!used[v])                {                    q.push(v);                    used[v] = 1;                }            }            else if(cd[v] > zd[u] + es[i].cost && zd[v] < zd[u] + es[i].cost)            {                cd[v] = zd[u] + es[i].cost;                if(!used[v])                {                    q.push(v);                    used[v] = 1;                }            }            else if(cd[v] > cd[u] + es[i].cost )            {                cd[v] = cd[u] + es[i].cost;                if(!used[v])                {                    q.push(v);                    used[v] = 1;                }            }        }    }}

树的直径:

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int SZ=100000+10;int first[SZ],nxt[SZ<<1];struct edge{    int from,to;}es[SZ<<1];int tot=0,n;void build(int ff,int tt){    es[++tot]=(edge){ff,tt};    nxt[tot]=first[ff];    first[ff]=tot;}int ans=0,pos;void dfs(int u,int f,int val){    if(val>ans)    {        ans=val;        pos=u;    }    for(int i=first[u];i!=-1;i=nxt[i])    {        int v=es[i].to;        if(v==f) continue;        dfs(v,u,val+1);    }}int main(){     memset(first,-1,sizeof(first));     int n;     scanf("%d",&n);     for(int i=1;i<=n;i++)     {        int l,r;        scanf("%d%d",&l,&r);        if(l) build(l,i),build(i,l);        if(r) build(r,i),build(i,r);     }     dfs(1,1,0);     ans=0;     dfs(pos,1,0);     cout<<ans<<endl;     return 0;} 
0 0
原创粉丝点击