• 图论模板


    最短路

    /*
    洛谷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
    ");
            else printf("N0
    ");
        }
        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
    ");
            else printf("N0
    ");
        }
        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
    ",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
    ",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
    ",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
    ",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
    ",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
    ");continue;}
            ans=ans==0x3f3f3f3f?-1:ans;ans=ans==0?1:ans;
            printf("%d
    ",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
    ",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
    ",max(dis[belong[i]],dis1[belong[i]]));
        }
    }
    
    int main()
    {
        n=read();m=read();
        Tarjan::solve1();
        LP::solve2();
        return 0;
    }
    Tarjan无向图缩点+树上最长链

    欧拉路

    网络流

    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    [Java]去除html中的标签或者元素属性(正则表达式)
    一份非常完整的 MySQL 规范
    前端统计图 echarts 实现简单柱状图
    获取一个表中的字段总数(mysql) Navicat如何导出Excel格式表结构 获取某个库中的一个表中的所有字段和数据类型
    【学习笔记】splay入门(更新中)
    【题解】P1972 [SDOI2009]HH的项链
    【题解】P2024 [NOI2001]食物链
    【题解】P1291 百事世界杯之旅
    【题解】P2602 数字计数
    【题解】P2831 愤怒的小鸟
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7705144.html
Copyright © 2020-2023  润新知