图论模板

最短路

/*
洛谷P3385
*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 200007

using namespace std;
int n,m,k,ans,cnt;
bool flag,inq[N];
int head[N],d[N];
struct edge{
    int u,v,net,w;
}e[N<<1];

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

inline void add(int u,int v,int w)
{
    e[++cnt].v=v;e[cnt].net=head[u];e[cnt].w=w;head[u]=cnt;
}

void init()
{
    memset(d,0,sizeof d);d[1]=0;
    memset(e,0,sizeof e);    
    memset(inq,0,sizeof inq);
    memset(head,0,sizeof head);
    cnt=0;flag=0;
}

void spfa(int u)
{
    inq[u]=1;
    for(int i=head[u];i;i=e[i].net)
    {
        int v=e[i].v;
        if(d[v]>d[u]+e[i].w) 
        {
            if(inq[v]){flag=1;return;}
            else d[v]=d[u]+e[i].w,spfa(v);
        }
    }inq[u]=0;
}

int main()
{
    int T,x,y,z;T=read();
    while(T--)
    {
        init();
        n=read();m=read();
        for(int i=1;i<=m;i++)
        {
            x=read();y=read();z=read();
            add(x,y,z);if(z>0) add(y,x,z);
        }
        for(int i=1;i<=n;i++) if(!flag) spfa(i);
        if(flag) printf("YE5\n");
        else printf("N0\n");
    }
    return 0;
}
dfs版spfa负环

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>

#define N 200007

using namespace std;
int n,m,k,ans,cnt;
bool flag,inq[N];
int head[N],d[N],in[N];
struct edge{
    int u,v,net,w;
}e[N<<1];

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

inline void add(int u,int v,int w)
{
    e[++cnt].v=v;e[cnt].net=head[u];e[cnt].w=w;head[u]=cnt;
}

void init()
{
    memset(d,127/3,sizeof d);
    memset(e,0,sizeof e);    
    memset(in,0,sizeof in);
    memset(inq,0,sizeof inq);
    memset(head,0,sizeof head);
    cnt=0;flag=0;
}

void spfa(int u)
{
    queue<int>q;
    memset(inq,0,sizeof inq);memset(d,127/3,sizeof d);
    memset(in,0,sizeof in);
    q.push(u);inq[u]=1;d[u]=0;
    while(!q.empty())
    {
        int u=q.front();q.pop();inq[u]=0;in[u]++;
        if(in[u]>n) {flag=1;return;}
        for(int i=head[u];i;i=e[i].net)
        {
            int v=e[i].v;
            if(d[v]>d[u]+e[i].w) 
            {
                d[v]=d[u]+e[i].w;
                if(!inq[v]) inq[v]=1,q.push(v);
            }
        }
    }
}

int main()
{
    freopen("ly.txt","r",stdin);
    int T,x,y,z;T=read();
    while(T--)
    {
        init();
        n=read();m=read();
        for(int i=1;i<=m;i++)
        {
            x=read();y=read();z=read();
            add(x,y,z);if(z>0) add(y,x,z);
        }
        //for(int i=1;i<=n;i++) if(!flag) spfa(i);
        spfa(1);
        if(flag) printf("YE5\n");
        else printf("N0\n");
    }
    return 0;
}
bfs版spfa负环

 

/*
P1339
*/
#include<bits/stdc++.h>

#define N 7000

using namespace std;
int n,m,ans,cnt,S,T;
int head[N],d[N];
bool vis[N];
struct edge{
    int u,v,net,dis;
    bool operator < (const edge &a)const{
            return dis>a.dis;
    }
}e[N<<1],p;

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

inline void add(int u,int v,int dis)
{
    e[++cnt].v=v;e[cnt].dis=dis;e[cnt].net=head[u];head[u]=cnt;
}

void dijkstra(int u)
{
    priority_queue<edge>q;
    p.u=u;p.dis=0;q.push(p);    
    memset(d,0x3f,sizeof d);d[S]=0;
    while(!q.empty())
    {
        edge tmp=q.top();q.pop();
        if(vis[tmp.u]) continue;
        vis[tmp.u]=true;
        for(int i=head[tmp.u];i;i=e[i].net)
        {
            int v=e[i].v;
            if(d[v]>d[tmp.u]+e[i].dis)
            {
                d[v]=d[tmp.u]+e[i].dis;
                p.u=v;p.dis=d[v];q.push(p);
            }
        }
    }
}

int main()
{
    int x,y,z; 
    n=read();m=read();S=read();T=read();
    for(int i=1;i<=m;i++)
    {
        x=read();y=read();z=read();
        add(x,y,z);add(y,x,z);
    }
    dijkstra(S);
    printf("%d\n",d[T]);
    return 0;
}
堆优化dijkstra

 

 

 

最小生成树

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
int n,m,x,y,z,ans,num,head[5001],fa[5001];
struct node{
    int from;
    int to;
    int dis;
}e[200001];

int cmp(const node &a,const node &b)
{
    if( a.dis<b.dis)return 1;
    else return 0;
}

int find(int x)
{
    if(fa[x]==x) return x;
    return find(fa[x]);
}

void un(int r1,int r2)
{
    int x=find(r1);
    int y=find(r2);
    if(x!=y);
    fa[y]=x;
}

int main()
{
    int k=0;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        cin>>e[i].from>>e[i].to>>e[i].dis;
    }
    for(int i=1;i<=n;i++) fa[i]=i;
    sort(e+1,e+m+1,cmp);
    for(int i=1;i<=m;i++)
    {
        if(find(e[i].from)!=find(e[i].to))
        {
            un(e[i].from,e[i].to);
            ans+=e[i].dis;
            k++;
        }
        if( k==n-1) break;
    }
    if(k!=n-1) cout<<"orz";
    else 
      cout<<ans<<endl;
    return 0;
}
年轻时代码

 

二分图

/*
P3386
单向边....
*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 1010

using namespace std;
int n,m,k,ans,cnt;
int p[N][N],lin[N],vis[N];

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

bool dfs(int u)
{
    for(int i=1;i<=m;i++)
    {
        if(p[u][i] && !vis[i])
        {
            vis[i]=1;
            if(lin[i]==0 || dfs(lin[i])){lin[i]=u;return 1;}
        }
    }return 0;
}

int main()
{
    int x,y;
    n=read();m=read();k=read();
    for(int i=1;i<=k;i++) 
    x=read(),y=read(),p[x][y]=1;
    for(int i=1;i<=n;i++)
    {
        memset(vis,0,sizeof vis);
        if(dfs(i)) ans++;
    }
    printf("%d\n",ans);
    return 0;
}
二分图匹配 

 

LCA

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 500010
#define S 21

using namespace std;
int deep[maxn],head[maxn],p1,p2,n,m,num,ans,s,x,y,fa[maxn][S+5];
struct node {
    int from;
    int to;
    int next;
}e[maxn*2];

void add(int from,int to)
{
    e[++num].from=from;
    e[num].to=to;
    e[num].next=head[from];
    head[from]=num;
}

int init()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

void swap(int &a,int &b)
{
    int t=a;a=b;b=t;
}

void get_fa()
{
    for(int j=1;j<=S;j++)
      for(int i=1;i<=n;i++)
        fa[i][j]=fa[fa[i][j-1]][j-1];
}

void Dfs(int now,int from,int c)
{
    fa[now][0]=from;
    deep[now]=c;
    for(int i=head[now];i;i=e[i].next)
     {
         int v=e[i].to;
         if(v!=from)
           Dfs(v,now,c+1);
     }
}

int get_same(int a,int t)
{
    for(int i=0;i<S;i++)
     if(t&(1<<i)) a=fa[a][i];
    return a;
}

int LCA(int a,int b)
{
    if(deep[a]<deep[b]) swap(a,b);
    a=get_same(a,deep[a]-deep[b]);
    if(a==b) return a;
    for(int i=S;i>=0;i--)
                       
    {
        if(fa[a][i]!=fa[b][i])
                {
                    a=fa[a][i];
                    b=fa[b][i];
              }
    }
        return fa[a][0];
}

int main()
{
    n=init();m=init();s=init();
    int x,y;
    for(int i=1;i<n;i++)
    { 
        x=init();y=init();
        add(x,y);
        add(y,x); 
    } 
    Dfs(s,s,0);
    get_fa();
    for(int i=1;i<=m;i++)
      {
          p1=init();p2=init();
        int ans=LCA(p1,p2);
        printf("%d\n",ans);
      }
    return 0;
}
倍增

 

Tarjan

 

/*
codevs4511
*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 200001

using namespace std;
int n,m,ans,cnt,num,top,now;
int head[N],scc[N],sta[N];
bool insta[N];
int dfn[N],low[N];
struct edge{
    int u,v,net;
}e[N<<1];


inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

inline void add(int u,int v)
{
    e[++cnt].v=v;e[cnt].net=head[u];head[u]=cnt;
}

void Tarjan(int u)
{
    dfn[u]=low[u]=++now;insta[u]=1;sta[++top]=u;
    for(int i=head[u];i;i=e[i].net)
    {
        int v=e[i].v;
        if(!dfn[v])
        {
            Tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(insta[v])
          low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        num=0;
        while(u!=sta[top])
        {
            num++;
            insta[sta[top]]=0;top--;
        }
        insta[sta[top]]=0;top--;num++;
        scc[++cnt]=num;
    }
}


int main()
{
    int x,y,z;n=read();
    for(int i=1;i<=n;i++)
    {
        x=read();
        add(i,x);
    }cnt=0;ans=0x3f3f3f3f;
    for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i);
    for(int i=1;i<=n;i++) if(scc[i]>1) ans=min(ans,scc[i]);
    printf("%d\n",ans);
    return 0;
}
Tarjan强连通分量

 

/*
洛谷P3388
*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 100007

using namespace std;
int n,m,ans,cnt,top,deg,root;
int head[N],st[N];
bool insta[N],cut[N];
int dfn[N],low[N];
struct edge{
    int u,v,net;
}e[N<<1];

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

inline void add(int u,int v)
{
    e[++cnt].v=v;e[cnt].net=head[u];head[u]=cnt;
}

void Tarjan(int u,int fa)
{
    low[u]=dfn[u]=++cnt;st[++top]=u;insta[u]=1;
    for(int i=head[u];i;i=e[i].net)
    {
        int v=e[i].v;
        if(!dfn[v])
        {
            Tarjan(v,u);low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u])
            {
                if(u==root) deg++;else cut[u]=1;
            }
        }
        else if(fa!=u) low[u]=min(low[u],dfn[v]);
    }
}

int main()
{
    freopen("ly.txt","r",stdin);
    int x,y;
    n=read();m=read();
    for(int i=1;i<=m;i++)
    {
        x=read();y=read();
        add(x,y);add(y,x);
    }cnt=0;
    for(int i=1;i<=n;i++)
    {
        if(!dfn[i]) Tarjan(root=i,0);
        if(deg>2) cut[root]=1;deg=0;
    }
    for(int i=1;i<=n;++i) if(cut[i])ans++;
    printf("%d\n",ans);
    for(int i=1;i<=n;i++)
        if(cut[i]) printf("%d ",i);
    return 0;
}
Tarjan割点

 

/*
hdu4738
1.原图可能不联通   这时不需要派人去炸桥 直接输出 0
2.有重边
3.可能有权值为0的桥  但我们必须要有一个人去带炸弹啊 所以这是输出 1
*/
#include<iostream>
#include<cstdio>
#include<cstring>

#define N 1001

using namespace std;
int n,m,cnt,ans,flag;
int head[N],dfn[N],low[N],fa[N];
struct edge{
    int u,v,w,net;
}e[N*N*2];

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

inline void add(int u,int v,int w)
{
    e[++cnt].v=v;e[cnt].w=w;e[cnt].net=head[u];head[u]=cnt;
}

void init()
{
    memset(low,0,sizeof low);memset(dfn,0,sizeof dfn);
    memset(fa,0,sizeof fa);memset(head,0,sizeof head);
    memset(e,0,sizeof e);cnt=flag=0;
}

void Tarjan(int u,int father)
{
    dfn[u]=low[u]=++cnt;
    for(int i=head[u];i;i=e[i].net)
    {
        int v=e[i].v;
        if(i==father+1) continue;
        if(!dfn[v])
        {
            Tarjan(v,i);low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u]) ans=min(ans,e[i].w);
        }
        low[u]=min(low[u],dfn[v]);//注意 
    }
}

int main()
{
    freopen("ly.txt","r",stdin);
    int x,y,z;
    while(1)
    {
        init();
        n=read();m=read();
        if(!n && !m) break;
        for(int i=1;i<=m;i++)
        {
            x=read();y=read();z=read();
            add(x,y,z);add(y,x,z);
        }cnt=0;
        ans=0x3f3f3f3f;
        for(int i=1;i<=n;i++) if(!dfn[i]) flag++,Tarjan(i,-1);
        if(flag>1){printf("0\n");continue;}
        ans=ans==0x3f3f3f3f?-1:ans;ans=ans==0?1:ans;
        printf("%d\n",ans);
    }
    return 0;
}
Tarjan求桥

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>

#define N 100007

using namespace std;
int n,m,k,ans,cnt,num;
int head[N],H[N],dp[N],in[N],dis[N];
int dfn[N],low[N],bel[N],sum[N];
bool inst[N],vis[N];
stack<int>st;
queue<int>q;
struct edge{
    int u,v,net,w;
}e[N<<1],E[N<<1];

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

inline void add1(int u,int v)
{
    e[++cnt].v=v;e[cnt].net=head[u];head[u]=cnt;
}

inline void add2(int u,int v)
{
    E[++cnt].v=v;E[cnt].net=H[u];H[u]=cnt;
}

namespace Tarjan
{
    void tarjan(int u)
    {
        dfn[u]=low[u]=++cnt;st.push(u);inst[u]=1;
        for(int i=head[u];i;i=e[i].net)
        {
            int v=e[i].v;
            if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]);
            else if(inst[v]) low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            num++;int tmp;
            do{
                tmp=st.top();
                inst[tmp]=0;st.pop();
                bel[tmp]=num;sum[num]+=dis[tmp];
            }while(tmp!=u);
        }
    }
    
    void rebuild()
    {
        cnt=0;
        for(int i=1;i<=n;i++)
          for(int j=head[i];j;j=e[j].net)
            if(bel[i]!=bel[e[j].v])
            {
                in[bel[e[j].v]]++;
                add2(bel[i],bel[e[j].v]);
            } 
    }
    
    void solve2()//这里不用vis数组!!!! 
    {
        for(int i=1;i<=num;i++) 
          if(!in[i]) q.push(i),dp[i]=sum[i];
        while(!q.empty())
        {
            int u=q.front();q.pop();
            for(int i=H[u];i;i=E[i].net)
            {
                int v=E[i].v;
                in[v]--;dp[v]=max(dp[v],dp[u]+sum[v]);
                if(!in[v]) q.push(v);
            }
        }
    }
    
    void solve1()
    {
        cnt=0;
        for(int i=1;i<=n;i++)
          if(!dfn[i]) tarjan(i);
        rebuild();solve2();
    }
}

int main()
{
    int x,y,z;
    n=read();m=read();
    for(int i=1;i<=n;i++) dis[i]=read();
    for(int i=1;i<=m;i++)
    x=read(),y=read(),add1(x,y);
    Tarjan::solve1();
    for(int i=1;i<=n;i++) ans=max(ans,dp[i]);
    printf("%d\n",ans);
    return 0;
}
Tarjan有向图缩点+dp最长路

 

#include<bits/stdc++.h>

#define N 20005
#define M 200005

using namespace std;
int n,m,id,dfn[N],low[N],head[N],head2[N],cnt;
int dis[N],dis1[N],mx,root;
int belong[N],belnum;
bool vis[N];
stack<int> stk;
struct Edge
{
    int u,v,val,next;
} edge[M<<1],e[M<<1];

inline int read()
{
    int x=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}

namespace Tarjan
{
    inline void add(int u,int v,int val)
    {
        edge[++cnt].v=v;edge[cnt].u=u;
        edge[cnt].val=val;edge[cnt].next=head[u];
        head[u]=cnt;
    }

    inline void tarjan(int u,int fa)
    {
        dfn[u]=low[u]=++id;
        vis[u]=1;stk.push(u);
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].v;
            if(!dfn[v])
            {
                tarjan(v,u);
                low[u]=min(low[u],low[v]);
            }
            else if(vis[v]&&v!=fa) low[u]=min(low[u],dfn[v]);
        }
        if(dfn[u]==low[u])
        {
            belnum++;int temp;
            do
            {
                temp=stk.top();
                belong[temp]=belnum;
                vis[temp]=0;stk.pop();
            }
            while(temp!=u);
        }
    }

    inline void solve1()
    {
        memset(head,-1,sizeof(head));
        for(int i=1,u,v,val; i<=m; i++)
        {
            u=read();v=read();val=read();
            add(u,v,val);add(v,u,val);
        }
        for(int i=1;i<=n;i++)
        if(!dfn[i])    tarjan(i,0);
    }
}

namespace LP
{
    inline void Add(int u,int v,int val)
    {
        e[++cnt].v=v;
        e[cnt].val=val;
        e[cnt].next=head2[u];
        head2[u]=cnt;
    }

    void dfs1(int u,int fa)
    {
        for(int i=head2[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(v==fa)    continue;
            dis[v]=dis[u]+e[i].val;
            if(dis[v]>mx) mx=dis[v],root=v;
            dfs1(v,u);
        }
    }

    void dfs2(int u,int fa)
    {
        for(int i=head2[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(v==fa)    continue;
            dis1[v]=dis1[u]+e[i].val;
            dfs2(v,u);
        }
    }

    inline void solve2()
    {
        cnt=0;
        memset(head2,-1,sizeof(head2));
        for(int i=1;i<=n;i++)
          for(int j=head[i]; j!=-1; j=edge[j].next)
            {
                if(belong[i]!=belong[edge[j].v])
                    Add(belong[i],belong[edge[j].v],edge[j].val);
            }
        dfs1(1,-1);mx=0;
        memset(dis,0,sizeof(dis));
        dfs1(root,-1);mx=0;
        dfs2(root,-1);
        for(int i=1; i<=n; i++)
        printf("%d\n",max(dis[belong[i]],dis1[belong[i]]));
    }
}

int main()
{
    n=read();m=read();
    Tarjan::solve1();
    LP::solve2();
    return 0;
}
Tarjan无向图缩点+树上最长链

 

 

欧拉路

 

 

 

网络流

posted @ 2017-10-21 16:36  安月冷  阅读(240)  评论(0编辑  收藏  举报