zoukankan      html  css  js  c++  java
  • NOI模板复习组——图论部分

    1.最小生成树:

    kruscal:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
    }edge[400005];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[400005];
    int f[200005];
    int head[200005];
    int cnt=1;
    int n,m;
    void init()
    {
        for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    int main()
    {
        read(n),read(m);
        init();
        for(int i=1;i<=m;i++)read(e[i].l),read(e[i].r),read(e[i].v);
        kruscal();
        return 0;
    }

    2.最短路:

    spfa(最好不要写,他死了)...

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
    }edge[1000005];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[500005];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[200005];
    int head[200005];
    ll dis[200005];
    bool used[200005];
    int cnt=1;
    int n,m,S,T;
    void init()
    {
        for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    int main()
    {
        read(n),read(m),read(S);
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z;
            read(x),read(y),read(z);
            add(x,y,z);//,add(y,x,z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        //kruscal();
        spfa(S);
        //diji(S);
        return 0;
    }

    dijisktra(这个比较好)

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
    }edge[1000005];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[500005];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[200005];
    int head[200005];
    ll dis[200005];
    bool used[200005];
    int cnt=1;
    int n,m,S,T;
    void init()
    {
        for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    int main()
    {
        read(n),read(m),read(S);
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z;
            read(x),read(y),read(z);
            add(x,y,z);//,add(y,x,z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        //kruscal();
        //spfa(S);
        diji(S);
        return 0;
    }

     3.LCA

    倍增版本:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
    }edge[5000005];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[5000005];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[500005];
    int head[500005];
    ll dis[500005];
    int fa[500005][25];
    int dep[500005];
    int siz[500005],son[500005],ttop[500005];
    bool used[500005];
    int cnt=1;
    int n,m,S,T;
    void init()
    {
        for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void tree_dfs(int x,int fx)
    {
        dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            tree_dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
        }
    }
    void tree_redfs(int x,int topx,int fx)
    {
        ttop[x]=topx;
        if(son[x])tree_redfs(son[x],topx,x);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx||to==son[x])continue;
            tree_redfs(to,to,x);
        }
    }
    int quick_jump_LCA(int x,int y)//倍增LCA
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
        if(x==y)return x;
        int ret;
        for(int i=20;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
            else ret=fa[x][i]; 
        }
        return ret;
    }
    int link_cut_LCA(int x,int y)//树剖LCA
    {
        while(ttop[x]!=ttop[y])
        {
            if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
            x=fa[ttop[x]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    int main()
    {
        read(n),read(m),read(S);
        init();
        for(int i=1;i<n;i++)
        {
            int x,y;ll z;
            read(x),read(y);//,read(z);
            add(x,y,z),add(y,x,z);//,add(y,x,z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        //kruscal();
        //spfa(S);
        //diji(S);
        tree_dfs(S,S);//,tree_redfs(S,S,S);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            printf("%d
    ",quick_jump_LCA(x,y));
        }
        return 0;
    }

    树剖版本:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #define ll long long
    using namespace std;
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
    }edge[5000005];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[5000005];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[500005];
    int head[500005];
    ll dis[500005];
    int fa[500005][25];
    int dep[500005];
    int siz[500005],son[500005],ttop[500005];
    bool used[500005];
    int cnt=1;
    int n,m,S,T;
    void init()
    {
        for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void tree_dfs(int x,int fx)
    {
        dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            tree_dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
        }
    }
    void tree_redfs(int x,int topx,int fx)
    {
        ttop[x]=topx;
        if(son[x])tree_redfs(son[x],topx,x);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx||to==son[x])continue;
            tree_redfs(to,to,x);
        }
    }
    int quick_jump_LCA(int x,int y)//倍增LCA
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
        if(x==y)return x;
        int ret;
        for(int i=20;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
            else ret=fa[x][i]; 
        }
        return ret;
    }
    int link_cut_LCA(int x,int y)//树剖LCA
    {
        while(ttop[x]!=ttop[y])
        {
            if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
            x=fa[ttop[x]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    int main()
    {
        read(n),read(m),read(S);
        init();
        for(int i=1;i<n;i++)
        {
            int x,y;ll z;
            read(x),read(y);//,read(z);
            add(x,y,z),add(y,x,z);//,add(y,x,z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        //kruscal();
        //spfa(S);
        //diji(S);
        tree_dfs(S,S),tree_redfs(S,S,S);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            printf("%d
    ",link_cut_LCA(x,y));
        }
        return 0;
    }

     4.tarjan

    有向图tarjan缩点+spfa最长路

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <vector>
    #define ll long long
    using namespace std;
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
    }edge[5000005];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[5000005];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[500005];
    int head[500005];
    ll dis[500005];
    ll va[500005];
    int dfn[500005],low[500005],posi[500005];
    ll src_num[500005],src_cnt;
    int my_stack[500005],top=0;
    int fa[500005][25];
    int dep[500005];
    int spe[500005],nu;
    int siz[500005],son[500005],ttop[500005];
    bool used[500005];
    int cnt=1,deep;
    int n,m,S,T;
    vector <int> v[500005];
    void init()
    {
        for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void tree_dfs(int x,int fx)
    {
        dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            tree_dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
        }
    }
    void tree_redfs(int x,int topx,int fx)
    {
        ttop[x]=topx;
        if(son[x])tree_redfs(son[x],topx,x);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx||to==son[x])continue;
            tree_redfs(to,to,x);
        }
    }
    int quick_jump_LCA(int x,int y)//倍增LCA
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
        if(x==y)return x;
        int ret;
        for(int i=20;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
            else ret=fa[x][i]; 
        }
        return ret;
    }
    int link_cut_LCA(int x,int y)//树剖LCA
    {
        while(ttop[x]!=ttop[y])
        {
            if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
            x=fa[ttop[x]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    void tarjan(int x)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(!dfn[to])
            {
                tarjan(to);
                low[x]=min(low[x],low[to]);
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]+=va[t];
                posi[t]=src_cnt;
            }
        }
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void min_dis_spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    void max_dis_spfa(int st)
    {
        memset(dis,0,sizeof(dis));
        used[st]=1;
        dis[st]=src_num[st];
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=0;i<v[u].size();i++)
            {
                int to=v[u][i];
                if(dis[to]<dis[u]+src_num[to])
                {
                    dis[to]=dis[u]+src_num[to];
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        ll ans=0;
        for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
        printf("%lld
    ",ans);
    }
    void build_MST()
    {
        kruscal();
    }
    void get_min_dis_road()
    {
        //min_dis_spfa(S);
        diji(S);
    }
    void solve_LCA()
    {
        tree_dfs(S,S),tree_redfs(S,S,S);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            printf("%d
    ",link_cut_LCA(x,y));
        }
    }
    void direc_tarjan()//有向图tarjan
    {
        for(int i=1;i<=n;i++)read(va[i]);
        read(S),read(nu);
        for(int i=1;i<=nu;i++)read(spe[i]);
        for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]==posi[to])continue;
                else v[posi[i]].push_back(posi[to]);
            }
        }
        max_dis_spfa(posi[S]);
    }
    
    int main()
    {
        read(n),read(m);
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z;
            read(x),read(y);//,read(z);
            add(x,y,z);//,add(y,x,z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        direc_tarjan();
        return 0;
    }

    无向图割边:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <vector>
    #define ll long long
    using namespace std;
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
    }edge[5000005];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[5000005];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[500005];
    int head[500005];
    ll dis[500005];
    ll va[500005];
    int dfn[500005],low[500005],posi[500005];
    ll src_num[500005],src_cnt;
    int my_stack[500005],top=0;
    int fa[500005][25];
    int dep[500005];
    int spe[500005],nu;
    int siz[500005],son[500005],ttop[500005];
    int inr[500005],our[500005];
    bool used[500005];
    int cnt=1,deep;
    int count_cut_line;
    int n,m,S,T;
    vector <int> v[500005];
    void init()
    {
        for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void tree_dfs(int x,int fx)
    {
        dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            tree_dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
        }
    }
    void tree_redfs(int x,int topx,int fx)
    {
        ttop[x]=topx;
        if(son[x])tree_redfs(son[x],topx,x);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx||to==son[x])continue;
            tree_redfs(to,to,x);
        }
    }
    int quick_jump_LCA(int x,int y)//倍增LCA
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
        if(x==y)return x;
        int ret;
        for(int i=20;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
            else ret=fa[x][i]; 
        }
        return ret;
    }
    int link_cut_LCA(int x,int y)//树剖LCA
    {
        while(ttop[x]!=ttop[y])
        {
            if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
            x=fa[ttop[x]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    void di_tarjan(int x)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(!dfn[to])
            {
                di_tarjan(to);
                low[x]=min(low[x],low[to]);
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]+=va[t];
                posi[t]=src_cnt;
            }
        }
    }
    void ed_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(edge[i].val==fx)continue;
            if(!dfn[to])
            {
                ed_tarjan(to,edge[i].val);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<low[to])count_cut_line++;
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void min_dis_spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    void max_dis_spfa(int st)
    {
        memset(dis,0,sizeof(dis));
        used[st]=1;
        dis[st]=src_num[st];
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=0;i<v[u].size();i++)
            {
                int to=v[u][i];
                if(dis[to]<dis[u]+src_num[to])
                {
                    dis[to]=dis[u]+src_num[to];
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        ll ans=0;
        for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
        printf("%lld
    ",ans);
    }
    void build_MST()
    {
        kruscal();
    }
    void get_min_dis_road()
    {
        //min_dis_spfa(S);
        diji(S);
    }
    void solve_LCA()
    {
        tree_dfs(S,S),tree_redfs(S,S,S);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            printf("%d
    ",link_cut_LCA(x,y));
        }
    }
    void direc_tarjan()//有向图tarjan
    {
        for(int i=1;i<=n;i++)read(va[i]);
        read(S),read(nu);
        for(int i=1;i<=nu;i++)read(spe[i]);
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]==posi[to])continue;
                else v[posi[i]].push_back(posi[to]);
            }
        }
        max_dis_spfa(posi[S]);
    }
    void cut_line_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
        printf("%d ",count_cut_line);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]!=posi[to])inr[posi[to]]++;
            }
        }
        int s=0;
        for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
        printf("%d
    ",(s+1)>>1);
    }
    int main()
    {
        read(n),read(m);
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z=i;
            read(x),read(y);//,read(z);
            add(x,y,z),add(y,x,z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        cut_line_tarjan();
        return 0;
    }

    无向图割点:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <vector>
    #define ll long long
    using namespace std;
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
    }edge[5000005];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[5000005];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[500005];
    int head[500005];
    ll dis[500005];
    ll va[500005];
    int dfn[500005],low[500005],posi[500005];
    ll src_num[500005],src_cnt;
    int my_stack[500005],top=0;
    int fa[500005][25];
    int dep[500005];
    int spe[500005],nu;
    int siz[500005],son[500005],ttop[500005];
    int inr[500005],our[500005];
    bool used[500005];
    int cnt=1,deep;
    int count_cut_line;
    int n,m,S,T;
    vector <int> v[500005];
    vector <int> peo[500005];
    vector <int> cut_point;
    bool cmp(vector <int> a,vector <int> b)
    {
        int lim=min(a.size(),b.size());
        for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
        return a.size()<b.size();
    }
    void init()
    {
        for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void tree_dfs(int x,int fx)
    {
        dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            tree_dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
        }
    }
    void tree_redfs(int x,int topx,int fx)
    {
        ttop[x]=topx;
        if(son[x])tree_redfs(son[x],topx,x);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx||to==son[x])continue;
            tree_redfs(to,to,x);
        }
    }
    int quick_jump_LCA(int x,int y)//倍增LCA
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
        if(x==y)return x;
        int ret;
        for(int i=20;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
            else ret=fa[x][i]; 
        }
        return ret;
    }
    int link_cut_LCA(int x,int y)//树剖LCA
    {
        while(ttop[x]!=ttop[y])
        {
            if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
            x=fa[ttop[x]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    void di_tarjan(int x)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(!dfn[to])
            {
                di_tarjan(to);
                low[x]=min(low[x],low[to]);
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]+=va[t];
                posi[t]=src_cnt;
            }
        }
    }
    void ed_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(edge[i].val==fx)continue;
            if(!dfn[to])
            {
                ed_tarjan(to,edge[i].val);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<low[to])count_cut_line++;
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void po_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            if(!dfn[to])
            {
                int pre=top;
                po_tarjan(to,x);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<=low[to])
                {
                    src_cnt++,posi[x]++;
                    int t=0;
                    while(top!=pre)
                    {
                        t=my_stack[top--];
                        peo[src_cnt].push_back(t);
                    }
                    peo[src_cnt].push_back(x);
                    sort(peo[src_cnt].begin(),peo[src_cnt].end());
                }
            }else low[x]=min(low[x],dfn[to]);
        }
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void min_dis_spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    void max_dis_spfa(int st)
    {
        memset(dis,0,sizeof(dis));
        used[st]=1;
        dis[st]=src_num[st];
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=0;i<v[u].size();i++)
            {
                int to=v[u][i];
                if(dis[to]<dis[u]+src_num[to])
                {
                    dis[to]=dis[u]+src_num[to];
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        ll ans=0;
        for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
        printf("%lld
    ",ans);
    }
    void build_MST()
    {
        kruscal();
    }
    void get_min_dis_road()
    {
        //min_dis_spfa(S);
        diji(S);
    }
    void solve_LCA()
    {
        tree_dfs(S,S),tree_redfs(S,S,S);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            printf("%d
    ",link_cut_LCA(x,y));
        }
    }
    void direc_tarjan()//有向图tarjan
    {
        for(int i=1;i<=n;i++)read(va[i]);
        read(S),read(nu);
        for(int i=1;i<=nu;i++)read(spe[i]);
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]==posi[to])continue;
                else v[posi[i]].push_back(posi[to]);
            }
        }
        max_dis_spfa(posi[S]);
    }
    void cut_line_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
        printf("%d ",count_cut_line);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]!=posi[to])inr[posi[to]]++;
            }
        }
        int s=0;
        for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
        printf("%d
    ",(s+1)>>1);
    }
    void cut_point_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
        for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
        printf("%d
    ",cut_point.size());
        for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
        printf("
    ");
        printf("%d
    ",src_cnt);
        sort(peo+1,peo+src_cnt+1,cmp);
        for(int i=1;i<=src_cnt;i++,printf("
    "))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
    }
    int main()
    {
        read(n),read(m);
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z=i;
            read(x),read(y);//,read(z);
            add(x,y,z),add(y,x,z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        cut_point_tarjan();
        return 0;
    }

    5.网络流

    最大流:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <vector>
    #define ll long long
    using namespace std;
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
        ll pri;
    }edge[5000005];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[5000005];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[500005];
    int head[500005];
    ll dis[500005];
    ll va[500005];
    int dfn[500005],low[500005],posi[500005];
    ll src_num[500005],src_cnt;
    int my_stack[500005],top=0;
    int fa[500005][25];
    int dep[500005];
    int spe[500005],nu;
    int siz[500005],son[500005],ttop[500005];
    int inr[500005],our[500005];
    int cur[500005];
    ll lim[500005];
    bool used[500005];
    int cnt=1,deep;
    int count_cut_line;
    int n,m,S,T;
    vector <int> v[500005];
    vector <int> peo[500005];
    vector <int> cut_point;
    bool cmp(vector <int> a,vector <int> b)
    {
        int lim=min(a.size(),b.size());
        for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
        return a.size()<b.size();
    }
    void init()
    {
        for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    void dadd(int l,int r,int w)
    {
        add(l,r,w),add(r,l,0);
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void tree_dfs(int x,int fx)
    {
        dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            tree_dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
        }
    }
    void tree_redfs(int x,int topx,int fx)
    {
        ttop[x]=topx;
        if(son[x])tree_redfs(son[x],topx,x);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx||to==son[x])continue;
            tree_redfs(to,to,x);
        }
    }
    int quick_jump_LCA(int x,int y)//倍增LCA
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
        if(x==y)return x;
        int ret;
        for(int i=20;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
            else ret=fa[x][i]; 
        }
        return ret;
    }
    int link_cut_LCA(int x,int y)//树剖LCA
    {
        while(ttop[x]!=ttop[y])
        {
            if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
            x=fa[ttop[x]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    void di_tarjan(int x)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(!dfn[to])
            {
                di_tarjan(to);
                low[x]=min(low[x],low[to]);
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]+=va[t];
                posi[t]=src_cnt;
            }
        }
    }
    void ed_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(edge[i].val==fx)continue;
            if(!dfn[to])
            {
                ed_tarjan(to,edge[i].val);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<low[to])count_cut_line++;
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void po_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            if(!dfn[to])
            {
                int pre=top;
                po_tarjan(to,x);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<=low[to])
                {
                    src_cnt++,posi[x]++;
                    int t=0;
                    while(top!=pre)
                    {
                        t=my_stack[top--];
                        peo[src_cnt].push_back(t);
                    }
                    peo[src_cnt].push_back(x);
                    sort(peo[src_cnt].begin(),peo[src_cnt].end());
                }
            }else low[x]=min(low[x],dfn[to]);
        }
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void min_dis_spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    void max_dis_spfa(int st)
    {
        memset(dis,0,sizeof(dis));
        used[st]=1;
        dis[st]=src_num[st];
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=0;i<v[u].size();i++)
            {
                int to=v[u][i];
                if(dis[to]<dis[u]+src_num[to])
                {
                    dis[to]=dis[u]+src_num[to];
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        ll ans=0;
        for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
        printf("%lld
    ",ans);
    }
    void build_MST()
    {
        kruscal();
    }
    void get_min_dis_road()
    {
        //min_dis_spfa(S);
        diji(S);
    }
    void solve_LCA()
    {
        tree_dfs(S,S),tree_redfs(S,S,S);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            printf("%d
    ",link_cut_LCA(x,y));
        }
    }
    void direc_tarjan()//有向图tarjan
    {
        for(int i=1;i<=n;i++)read(va[i]);
        read(S),read(nu);
        for(int i=1;i<=nu;i++)read(spe[i]);
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]==posi[to])continue;
                else v[posi[i]].push_back(posi[to]);
            }
        }
        max_dis_spfa(posi[S]);
    }
    void cut_line_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
        printf("%d ",count_cut_line);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]!=posi[to])inr[posi[to]]++;
            }
        }
        int s=0;
        for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
        printf("%d
    ",(s+1)>>1);
    }
    void cut_point_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
        for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
        printf("%d
    ",cut_point.size());
        for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
        printf("
    ");
        printf("%d
    ",src_cnt);
        sort(peo+1,peo+src_cnt+1,cmp);
        for(int i=1;i<=src_cnt;i++,printf("
    "))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
    }
    int ide(int x)
    {
        return x&1?x+1:x-1;
    }
    bool dinic_bfs()
    {
        memset(dis,0,sizeof(dis));
        memcpy(cur,head,sizeof(head));
        dis[S]=1;
        queue <int> M;
        M.push(S);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
            }
        }
        return dis[T];
    }
    ll dinic_dfs(int x,ll lim)
    {
        if(x==T)return lim;
        ll ret=0;
        for(int i=cur[x];i;i=edge[i].nxt)
        {
            cur[x]=i;
            int to=edge[i].to;
            if(edge[i].val&&dis[to]==dis[x]+1)
            {
                ll temp=dinic_dfs(to,min(lim,edge[i].val));
                if(temp)
                {
                    ret+=temp,lim-=temp;
                    edge[i].val-=temp,edge[ide(i)].val+=temp;
                    if(!lim)break;
                }
            }
        }
        return ret;
    }
    ll dinic()
    {
        ll ans=0;
        while(dinic_bfs())ans+=dinic_dfs(S,INF);
        return ans;
    }
    void max_flow()
    {
        printf("%lld
    ",dinic());
    }
    int main()
    {
        read(n),read(m),read(S),read(T);
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z;
            read(x),read(y),read(z);
            dadd(x,y,z);//,add(y,x,z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        max_flow();
        return 0;
    }

    费用流:

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <vector>
    #define ll long long
    using namespace std;
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
        ll pri;
    }edge[5000005];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[5000005];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[500005];
    int head[500005];
    ll dis[500005];
    ll va[500005];
    int dfn[500005],low[500005],posi[500005];
    ll src_num[500005],src_cnt;
    int my_stack[500005],top=0;
    int fa[500005][25];
    int dep[500005];
    int spe[500005],nu;
    int siz[500005],son[500005],ttop[500005];
    int inr[500005],our[500005];
    int cur[500005];
    int pre[500005];
    ll lim[500005];
    bool used[500005];
    int cnt=1,deep;
    int count_cut_line;
    int n,m,S,T;
    vector <int> v[500005];
    vector <int> peo[500005];
    vector <int> cut_point;
    bool cmp(vector <int> a,vector <int> b)
    {
        int lim=min(a.size(),b.size());
        for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
        return a.size()<b.size();
    }
    void init()
    {
        for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    void dadd(int l,int r,int w)
    {
        add(l,r,w),add(r,l,0);
    }
    void cost_add(int l,int r,ll w,ll p)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        edge[cnt].pri=p;
        head[l]=cnt++;
    }
    void cost_dadd(int l,int r,ll w,ll p)
    {
        cost_add(l,r,w,p),cost_add(r,l,0,-p);
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void tree_dfs(int x,int fx)
    {
        dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            tree_dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
        }
    }
    void tree_redfs(int x,int topx,int fx)
    {
        ttop[x]=topx;
        if(son[x])tree_redfs(son[x],topx,x);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx||to==son[x])continue;
            tree_redfs(to,to,x);
        }
    }
    int quick_jump_LCA(int x,int y)//倍增LCA
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
        if(x==y)return x;
        int ret;
        for(int i=20;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
            else ret=fa[x][i]; 
        }
        return ret;
    }
    int link_cut_LCA(int x,int y)//树剖LCA
    {
        while(ttop[x]!=ttop[y])
        {
            if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
            x=fa[ttop[x]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    void di_tarjan(int x)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(!dfn[to])
            {
                di_tarjan(to);
                low[x]=min(low[x],low[to]);
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]+=va[t];
                posi[t]=src_cnt;
            }
        }
    }
    void ed_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(edge[i].val==fx)continue;
            if(!dfn[to])
            {
                ed_tarjan(to,edge[i].val);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<low[to])count_cut_line++;
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void po_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            if(!dfn[to])
            {
                int pre=top;
                po_tarjan(to,x);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<=low[to])
                {
                    src_cnt++,posi[x]++;
                    int t=0;
                    while(top!=pre)
                    {
                        t=my_stack[top--];
                        peo[src_cnt].push_back(t);
                    }
                    peo[src_cnt].push_back(x);
                    sort(peo[src_cnt].begin(),peo[src_cnt].end());
                }
            }else low[x]=min(low[x],dfn[to]);
        }
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void min_dis_spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    void max_dis_spfa(int st)
    {
        memset(dis,0,sizeof(dis));
        used[st]=1;
        dis[st]=src_num[st];
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=0;i<v[u].size();i++)
            {
                int to=v[u][i];
                if(dis[to]<dis[u]+src_num[to])
                {
                    dis[to]=dis[u]+src_num[to];
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        ll ans=0;
        for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
        printf("%lld
    ",ans);
    }
    void build_MST()
    {
        kruscal();
    }
    void get_min_dis_road()
    {
        //min_dis_spfa(S);
        diji(S);
    }
    void solve_LCA()
    {
        tree_dfs(S,S),tree_redfs(S,S,S);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            printf("%d
    ",link_cut_LCA(x,y));
        }
    }
    void direc_tarjan()//有向图tarjan
    {
        for(int i=1;i<=n;i++)read(va[i]);
        read(S),read(nu);
        for(int i=1;i<=nu;i++)read(spe[i]);
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]==posi[to])continue;
                else v[posi[i]].push_back(posi[to]);
            }
        }
        max_dis_spfa(posi[S]);
    }
    void cut_line_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
        printf("%d ",count_cut_line);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]!=posi[to])inr[posi[to]]++;
            }
        }
        int s=0;
        for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
        printf("%d
    ",(s+1)>>1);
    }
    void cut_point_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
        for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
        printf("%d
    ",cut_point.size());
        for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
        printf("
    ");
        printf("%d
    ",src_cnt);
        sort(peo+1,peo+src_cnt+1,cmp);
        for(int i=1;i<=src_cnt;i++,printf("
    "))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
    }
    int ide(int x)
    {
        return x&1?x+1:x-1;
    }
    bool dinic_bfs()
    {
        memset(dis,0,sizeof(dis));
        memcpy(cur,head,sizeof(head));
        dis[S]=1;
        queue <int> M;
        M.push(S);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
            }
        }
        return dis[T];
    }
    ll dinic_dfs(int x,ll lim)
    {
        if(x==T)return lim;
        ll ret=0;
        for(int i=cur[x];i;i=edge[i].nxt)
        {
            cur[x]=i;
            int to=edge[i].to;
            if(edge[i].val&&dis[to]==dis[x]+1)
            {
                ll temp=dinic_dfs(to,min(lim,edge[i].val));
                if(temp)
                {
                    ret+=temp,lim-=temp;
                    edge[i].val-=temp,edge[ide(i)].val+=temp;
                    if(!lim)break;
                }
            }
        }
        return ret;
    }
    ll dinic()
    {
        ll ans=0;
        while(dinic_bfs())ans+=dinic_dfs(S,INF);
        return ans;
    }
    void max_flow()
    {
        printf("%lld
    ",dinic());
    }
    bool EK_spfa()
    {
        memset(pre,-1,sizeof(pre));
        memset(f,0,sizeof(f));
        memset(dis,0x3f,sizeof(dis));
        dis[S]=0,lim[S]=INF,used[S]=1;
        queue <int> M;
        M.push(S);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
                {
                    dis[to]=dis[u]+edge[i].pri;
                    pre[to]=i,f[to]=u,lim[to]=min(lim[u],edge[i].val);
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        return pre[T]!=-1;
    }
    void EK()
    {
        ll maxf=0,minv=0;
        while(EK_spfa())
        {
            maxf+=lim[T],minv+=dis[T]*lim[T];
            int temp=T;
            while(temp!=S)edge[pre[temp]].val-=lim[T],edge[ide(pre[temp])].val+=lim[T],temp=f[temp];
        }
        printf("%lld %lld
    ",maxf,minv);
    }
    void min_cost_max_flow()
    {
        S=1,T=n;
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z,w;
            read(x),read(y),read(z),read(w);
            cost_dadd(x,y,z,w);
        }
        EK();
    }
    int main()
    {
        read(n),read(m);//,read(S),read(T);
        init();
        min_cost_max_flow();
        return 0;
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z;
            read(x),read(y),read(z);
            dadd(x,y,z);//,add(y,x,z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        max_flow();
        return 0;
    }

    有源汇上下界最大流

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <vector>
    #define ll long long
    using namespace std;
    const int maxn=2000005;
    const int maxm=5000005;
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
        ll pri;
    }edge[maxm];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[maxm];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[maxn];
    int head[maxn];
    ll dis[maxn];
    ll va[maxn];
    int dfn[maxn],low[maxn],posi[maxn];
    ll src_num[maxn],src_cnt;
    int my_stack[maxn],top=0;
    int fa[maxn][25];
    int dep[maxn];
    int spe[maxn],nu;
    int siz[maxn],son[maxn],ttop[maxn];
    int inr[maxn],our[maxn];
    int cur[maxn];
    int pre[maxn];
    ll lim[maxn];
    bool used[maxn];
    ll fin[maxn],fout[maxn];
    int cnt=1,deep;
    int count_cut_line;
    int n,m,S,T;
    vector <int> v[maxn];
    vector <int> peo[maxn];
    vector <int> cut_point;
    bool cmp(vector <int> a,vector <int> b)
    {
        int lim=min(a.size(),b.size());
        for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
        return a.size()<b.size();
    }
    void init()
    {
        //for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    void dadd(int l,int r,ll w)
    {
        add(l,r,w),add(r,l,0);
    }
    void cost_add(int l,int r,ll w,ll p)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        edge[cnt].pri=p;
        head[l]=cnt++;
    }
    void cost_dadd(int l,int r,ll w,ll p)
    {
        cost_add(l,r,w,p),cost_add(r,l,0,-p);
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void tree_dfs(int x,int fx)
    {
        dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            tree_dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
        }
    }
    void tree_redfs(int x,int topx,int fx)
    {
        ttop[x]=topx;
        if(son[x])tree_redfs(son[x],topx,x);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx||to==son[x])continue;
            tree_redfs(to,to,x);
        }
    }
    int quick_jump_LCA(int x,int y)//倍增LCA
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
        if(x==y)return x;
        int ret;
        for(int i=20;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
            else ret=fa[x][i]; 
        }
        return ret;
    }
    int link_cut_LCA(int x,int y)//树剖LCA
    {
        while(ttop[x]!=ttop[y])
        {
            if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
            x=fa[ttop[x]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    void di_tarjan(int x)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(!dfn[to])
            {
                di_tarjan(to);
                low[x]=min(low[x],low[to]);
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void ed_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(edge[i].val==fx)continue;
            if(!dfn[to])
            {
                ed_tarjan(to,edge[i].val);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<low[to])count_cut_line++;
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void po_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            if(!dfn[to])
            {
                int pre=top;
                po_tarjan(to,x);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<=low[to])
                {
                    src_cnt++,posi[x]++;
                    int t=0;
                    while(top!=pre)
                    {
                        t=my_stack[top--];
                        peo[src_cnt].push_back(t);
                    }
                    peo[src_cnt].push_back(x);
                    sort(peo[src_cnt].begin(),peo[src_cnt].end());
                }
            }else low[x]=min(low[x],dfn[to]);
        }
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void min_dis_spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    void max_dis_spfa(int st)
    {
        memset(dis,0,sizeof(dis));
        used[st]=1;
        dis[st]=src_num[st];
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=0;i<v[u].size();i++)
            {
                int to=v[u][i];
                if(dis[to]<dis[u]+src_num[to])
                {
                    dis[to]=dis[u]+src_num[to];
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        ll ans=0;
        for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
        printf("%lld
    ",ans);
    }
    void build_MST()
    {
        kruscal();
    }
    void get_min_dis_road()
    {
        //min_dis_spfa(S);
        diji(S);
    }
    void solve_LCA()
    {
        tree_dfs(S,S),tree_redfs(S,S,S);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            printf("%d
    ",link_cut_LCA(x,y));
        }
    }
    void direc_tarjan()//有向图tarjan
    {
        for(int i=1;i<=n;i++)read(va[i]);
        read(S),read(nu);
        for(int i=1;i<=nu;i++)read(spe[i]);
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]==posi[to])continue;
                else v[posi[i]].push_back(posi[to]);
            }
        }
        max_dis_spfa(posi[S]);
    }
    void cut_line_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
        printf("%d ",count_cut_line);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]!=posi[to])inr[posi[to]]++;
            }
        }
        int s=0;
        for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
        printf("%d
    ",(s+1)>>1);
    }
    void cut_point_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
        for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
        printf("%d
    ",cut_point.size());
        for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
        printf("
    ");
        printf("%d
    ",src_cnt);
        sort(peo+1,peo+src_cnt+1,cmp);
        for(int i=1;i<=src_cnt;i++,printf("
    "))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
    }
    int ide(int x)
    {
        return x&1?x+1:x-1;
    }
    bool dinic_bfs()
    {
        memset(dis,0,sizeof(dis));
        memcpy(cur,head,sizeof(head));
        dis[S]=1;
        queue <int> M;
        M.push(S);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
            }
        }
        return dis[T];
    }
    ll dinic_dfs(int x,ll lim)
    {
        if(x==T)return lim;
        ll ret=0;
        for(int i=cur[x];i;i=edge[i].nxt)
        {
            cur[x]=i;
            int to=edge[i].to;
            if(edge[i].val&&dis[to]==dis[x]+1)
            {
                ll temp=dinic_dfs(to,min(lim,edge[i].val));
                if(temp)
                {
                    ret+=temp,lim-=temp;
                    edge[i].val-=temp,edge[ide(i)].val+=temp;
                    if(!lim)break;
                }
            }
        }
        return ret;
    }
    ll dinic()
    {
        ll ans=0;
        while(dinic_bfs())ans+=dinic_dfs(S,INF);
        return ans;
    }
    void max_flow()
    {
        printf("%lld
    ",dinic());
    }
    bool EK_spfa()
    {
        memset(pre,-1,sizeof(pre));
        memset(f,0,sizeof(f));
        memset(dis,0x3f,sizeof(dis));
        dis[S]=0,lim[S]=INF,used[S]=1;
        queue <int> M;
        M.push(S);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
                {
                    dis[to]=dis[u]+edge[i].pri;
                    pre[to]=i,f[to]=u,lim[to]=min(lim[u],edge[i].val);
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        return pre[T]!=-1;
    }
    void EK()
    {
        ll maxf=0,minv=0;
        while(EK_spfa())
        {
            maxf+=lim[T],minv+=dis[T]*lim[T];
            int temp=T;
            while(temp!=S)edge[pre[temp]].val-=lim[T],edge[ide(pre[temp])].val+=lim[T],temp=f[temp];
        }
        printf("%lld %lld
    ",maxf,minv);
    }
    void min_cost_max_flow()
    {
        S=1,T=n;
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z,w;
            read(x),read(y),read(z),read(w);
            cost_dadd(x,y,z,w);
        }
        EK();
    }
    void two_SAT()
    {
        for(int i=1;i<=m;i++)
        {
            int x,y,z,w;
            read(x),read(y),read(z),read(w);
            if(y==1&&w==1)add(x+n,z,0),add(z+n,x,0);
            else if(y==1)add(x+n,z+n,0),add(z,x,0);
            else if(w==1)add(x,z,0),add(z+n,x+n,0);
            else add(x,z+n,0),add(z,x+n,0);
        }
        n<<=1;
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        n>>=1;
        for(int i=1;i<=n;i++)if(posi[i]==posi[i+n]){printf("IMPOSSIBLE
    ");exit(0);}
        printf("POSSIBLE
    ");
        for(int i=1;i<=n;i++)
        {
            if(posi[i]<posi[i+n])printf("1 ");
            else printf("0 ");
        }
        printf("
    ");
    }
    bool dfs(int x)
    {
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(used[to])continue;
            used[to]=1;
            if(!f[to]||dfs(f[to])){f[to]=x;return 1;}
        }
        return 0;
    }
    int hungary()
    {
        int ret=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n+m;j++)used[j]=0;
            if(dfs(i))ret++;
        }
        return ret;
    }
    void two_match()
    {
        read(n),read(m),read(S);
        for(int i=1;i<=S;i++)
        {
            int x,y;
            read(x),read(y);
            if(x>n||y>m)continue;
            add(x,y+n,0),add(y+n,x,0);
        }
        printf("%d
    ",hungary());
    }
    void upper_lower_maxflow()
    {
        int temps=S,tempt=T;
        S=n+1,T=n+2;
        ll sum=0;
        for(int i=1;i<=n;i++)
        {
            if(fin[i]>fout[i])dadd(S,i,fin[i]-fout[i]),sum+=fin[i]-fout[i];
            else dadd(i,T,fout[i]-fin[i]);
        }
        if(dinic()<sum)printf("please go home to sleep
    ");
        else S=temps,T=tempt,printf("%lld
    ",dinic());
    }
    void upper_lower_minflow()
    {
        int temps=S,tempt=T;
        S=n+1,T=n+2;
        ll sum=0;
        for(int i=1;i<=n;i++)
        {
            if(fin[i]>fout[i])dadd(S,i,fin[i]-fout[i]),sum+=fin[i]-fout[i];
            else dadd(i,T,fout[i]-fin[i]);
        }
        if(dinic()<sum)printf("please go home to sleep
    ");
        else S=tempt,T=temps,printf("%lld
    ",INF-dinic());
    }
    int main()
    {
        read(n),read(m),read(S),read(T);
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z,w;
            read(x),read(y),read(z),read(w);
            fin[y]+=z,fout[x]+=z;
            dadd(x,y,w-z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        dadd(T,S,INF);
        upper_lower_maxflow();
        return 0;
    }

    有源汇上下界最小流

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <vector>
    #define ll long long
    using namespace std;
    const int maxn=2000005;
    const int maxm=5000005;
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
        ll pri;
    }edge[maxm];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[maxm];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[maxn];
    int head[maxn];
    ll dis[maxn];
    ll va[maxn];
    int dfn[maxn],low[maxn],posi[maxn];
    ll src_num[maxn],src_cnt;
    int my_stack[maxn],top=0;
    int fa[maxn][25];
    int dep[maxn];
    int spe[maxn],nu;
    int siz[maxn],son[maxn],ttop[maxn];
    int inr[maxn],our[maxn];
    int cur[maxn];
    int pre[maxn];
    ll lim[maxn];
    bool used[maxn];
    ll fin[maxn],fout[maxn];
    int cnt=1,deep;
    int count_cut_line;
    int n,m,S,T;
    vector <int> v[maxn];
    vector <int> peo[maxn];
    vector <int> cut_point;
    bool cmp(vector <int> a,vector <int> b)
    {
        int lim=min(a.size(),b.size());
        for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
        return a.size()<b.size();
    }
    void init()
    {
        //for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    void dadd(int l,int r,ll w)
    {
        add(l,r,w),add(r,l,0);
    }
    void cost_add(int l,int r,ll w,ll p)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        edge[cnt].pri=p;
        head[l]=cnt++;
    }
    void cost_dadd(int l,int r,ll w,ll p)
    {
        cost_add(l,r,w,p),cost_add(r,l,0,-p);
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void tree_dfs(int x,int fx)
    {
        dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            tree_dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
        }
    }
    void tree_redfs(int x,int topx,int fx)
    {
        ttop[x]=topx;
        if(son[x])tree_redfs(son[x],topx,x);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx||to==son[x])continue;
            tree_redfs(to,to,x);
        }
    }
    int quick_jump_LCA(int x,int y)//倍增LCA
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
        if(x==y)return x;
        int ret;
        for(int i=20;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
            else ret=fa[x][i]; 
        }
        return ret;
    }
    int link_cut_LCA(int x,int y)//树剖LCA
    {
        while(ttop[x]!=ttop[y])
        {
            if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
            x=fa[ttop[x]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    void di_tarjan(int x)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(!dfn[to])
            {
                di_tarjan(to);
                low[x]=min(low[x],low[to]);
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void ed_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(edge[i].val==fx)continue;
            if(!dfn[to])
            {
                ed_tarjan(to,edge[i].val);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<low[to])count_cut_line++;
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void po_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            if(!dfn[to])
            {
                int pre=top;
                po_tarjan(to,x);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<=low[to])
                {
                    src_cnt++,posi[x]++;
                    int t=0;
                    while(top!=pre)
                    {
                        t=my_stack[top--];
                        peo[src_cnt].push_back(t);
                    }
                    peo[src_cnt].push_back(x);
                    sort(peo[src_cnt].begin(),peo[src_cnt].end());
                }
            }else low[x]=min(low[x],dfn[to]);
        }
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void min_dis_spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    void max_dis_spfa(int st)
    {
        memset(dis,0,sizeof(dis));
        used[st]=1;
        dis[st]=src_num[st];
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=0;i<v[u].size();i++)
            {
                int to=v[u][i];
                if(dis[to]<dis[u]+src_num[to])
                {
                    dis[to]=dis[u]+src_num[to];
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        ll ans=0;
        for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
        printf("%lld
    ",ans);
    }
    void build_MST()
    {
        kruscal();
    }
    void get_min_dis_road()
    {
        //min_dis_spfa(S);
        diji(S);
    }
    void solve_LCA()
    {
        tree_dfs(S,S),tree_redfs(S,S,S);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            printf("%d
    ",link_cut_LCA(x,y));
        }
    }
    void direc_tarjan()//有向图tarjan
    {
        for(int i=1;i<=n;i++)read(va[i]);
        read(S),read(nu);
        for(int i=1;i<=nu;i++)read(spe[i]);
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]==posi[to])continue;
                else v[posi[i]].push_back(posi[to]);
            }
        }
        max_dis_spfa(posi[S]);
    }
    void cut_line_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
        printf("%d ",count_cut_line);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]!=posi[to])inr[posi[to]]++;
            }
        }
        int s=0;
        for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
        printf("%d
    ",(s+1)>>1);
    }
    void cut_point_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
        for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
        printf("%d
    ",cut_point.size());
        for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
        printf("
    ");
        printf("%d
    ",src_cnt);
        sort(peo+1,peo+src_cnt+1,cmp);
        for(int i=1;i<=src_cnt;i++,printf("
    "))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
    }
    int ide(int x)
    {
        return x&1?x+1:x-1;
    }
    bool dinic_bfs()
    {
        memset(dis,0,sizeof(dis));
        memcpy(cur,head,sizeof(head));
        dis[S]=1;
        queue <int> M;
        M.push(S);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
            }
        }
        return dis[T];
    }
    ll dinic_dfs(int x,ll lim)
    {
        if(x==T)return lim;
        ll ret=0;
        for(int i=cur[x];i;i=edge[i].nxt)
        {
            cur[x]=i;
            int to=edge[i].to;
            if(edge[i].val&&dis[to]==dis[x]+1)
            {
                ll temp=dinic_dfs(to,min(lim,edge[i].val));
                if(temp)
                {
                    ret+=temp,lim-=temp;
                    edge[i].val-=temp,edge[ide(i)].val+=temp;
                    if(!lim)break;
                }
            }
        }
        return ret;
    }
    ll dinic()
    {
        ll ans=0;
        while(dinic_bfs())ans+=dinic_dfs(S,INF);
        return ans;
    }
    void max_flow()
    {
        printf("%lld
    ",dinic());
    }
    bool EK_spfa()
    {
        memset(pre,-1,sizeof(pre));
        memset(f,0,sizeof(f));
        memset(dis,0x3f,sizeof(dis));
        dis[S]=0,lim[S]=INF,used[S]=1;
        queue <int> M;
        M.push(S);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
                {
                    dis[to]=dis[u]+edge[i].pri;
                    pre[to]=i,f[to]=u,lim[to]=min(lim[u],edge[i].val);
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        return pre[T]!=-1;
    }
    void EK()
    {
        ll maxf=0,minv=0;
        while(EK_spfa())
        {
            maxf+=lim[T],minv+=dis[T]*lim[T];
            int temp=T;
            while(temp!=S)edge[pre[temp]].val-=lim[T],edge[ide(pre[temp])].val+=lim[T],temp=f[temp];
        }
        printf("%lld %lld
    ",maxf,minv);
    }
    void min_cost_max_flow()
    {
        S=1,T=n;
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z,w;
            read(x),read(y),read(z),read(w);
            cost_dadd(x,y,z,w);
        }
        EK();
    }
    void two_SAT()
    {
        for(int i=1;i<=m;i++)
        {
            int x,y,z,w;
            read(x),read(y),read(z),read(w);
            if(y==1&&w==1)add(x+n,z,0),add(z+n,x,0);
            else if(y==1)add(x+n,z+n,0),add(z,x,0);
            else if(w==1)add(x,z,0),add(z+n,x+n,0);
            else add(x,z+n,0),add(z,x+n,0);
        }
        n<<=1;
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        n>>=1;
        for(int i=1;i<=n;i++)if(posi[i]==posi[i+n]){printf("IMPOSSIBLE
    ");exit(0);}
        printf("POSSIBLE
    ");
        for(int i=1;i<=n;i++)
        {
            if(posi[i]<posi[i+n])printf("1 ");
            else printf("0 ");
        }
        printf("
    ");
    }
    bool dfs(int x)
    {
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(used[to])continue;
            used[to]=1;
            if(!f[to]||dfs(f[to])){f[to]=x;return 1;}
        }
        return 0;
    }
    int hungary()
    {
        int ret=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n+m;j++)used[j]=0;
            if(dfs(i))ret++;
        }
        return ret;
    }
    void two_match()
    {
        read(n),read(m),read(S);
        for(int i=1;i<=S;i++)
        {
            int x,y;
            read(x),read(y);
            if(x>n||y>m)continue;
            add(x,y+n,0),add(y+n,x,0);
        }
        printf("%d
    ",hungary());
    }
    void upper_lower_maxflow()
    {
        int temps=S,tempt=T;
        S=n+1,T=n+2;
        ll sum=0;
        for(int i=1;i<=n;i++)
        {
            if(fin[i]>fout[i])dadd(S,i,fin[i]-fout[i]),sum+=fin[i]-fout[i];
            else dadd(i,T,fout[i]-fin[i]);
        }
        if(dinic()<sum)printf("please go home to sleep
    ");
        else S=temps,T=tempt,printf("%lld
    ",dinic());
    }
    void upper_lower_minflow()
    {
        int temps=S,tempt=T;
        S=n+1,T=n+2;
        ll sum=0;
        for(int i=1;i<=n;i++)
        {
            if(fin[i]>fout[i])dadd(S,i,fin[i]-fout[i]),sum+=fin[i]-fout[i];
            else dadd(i,T,fout[i]-fin[i]);
        }
        if(dinic()<sum)printf("please go home to sleep
    ");
        else S=tempt,T=temps,printf("%lld
    ",INF-dinic());
    }
    int main()
    {
        read(n),read(m),read(S),read(T);
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z,w;
            read(x),read(y),read(z),read(w);
            fin[y]+=z,fout[x]+=z;
            dadd(x,y,w-z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        dadd(T,S,INF);
        upper_lower_minflow();
        return 0;
    }

    6.2-SAT

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <vector>
    #define ll long long
    using namespace std;
    const int maxn=2000005;
    const int maxm=5000005;
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
        ll pri;
    }edge[maxm];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[maxm];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[maxn];
    int head[maxn];
    ll dis[maxn];
    ll va[maxn];
    int dfn[maxn],low[maxn],posi[maxn];
    ll src_num[maxn],src_cnt;
    int my_stack[maxn],top=0;
    int fa[maxn][25];
    int dep[maxn];
    int spe[maxn],nu;
    int siz[maxn],son[maxn],ttop[maxn];
    int inr[maxn],our[maxn];
    int cur[maxn];
    int pre[maxn];
    ll lim[maxn];
    bool used[maxn];
    int cnt=1,deep;
    int count_cut_line;
    int n,m,S,T;
    vector <int> v[maxn];
    vector <int> peo[maxn];
    vector <int> cut_point;
    bool cmp(vector <int> a,vector <int> b)
    {
        int lim=min(a.size(),b.size());
        for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
        return a.size()<b.size();
    }
    void init()
    {
        //for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    void dadd(int l,int r,int w)
    {
        add(l,r,w),add(r,l,0);
    }
    void cost_add(int l,int r,ll w,ll p)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        edge[cnt].pri=p;
        head[l]=cnt++;
    }
    void cost_dadd(int l,int r,ll w,ll p)
    {
        cost_add(l,r,w,p),cost_add(r,l,0,-p);
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void tree_dfs(int x,int fx)
    {
        dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            tree_dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
        }
    }
    void tree_redfs(int x,int topx,int fx)
    {
        ttop[x]=topx;
        if(son[x])tree_redfs(son[x],topx,x);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx||to==son[x])continue;
            tree_redfs(to,to,x);
        }
    }
    int quick_jump_LCA(int x,int y)//倍增LCA
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
        if(x==y)return x;
        int ret;
        for(int i=20;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
            else ret=fa[x][i]; 
        }
        return ret;
    }
    int link_cut_LCA(int x,int y)//树剖LCA
    {
        while(ttop[x]!=ttop[y])
        {
            if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
            x=fa[ttop[x]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    void di_tarjan(int x)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(!dfn[to])
            {
                di_tarjan(to);
                low[x]=min(low[x],low[to]);
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void ed_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(edge[i].val==fx)continue;
            if(!dfn[to])
            {
                ed_tarjan(to,edge[i].val);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<low[to])count_cut_line++;
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void po_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            if(!dfn[to])
            {
                int pre=top;
                po_tarjan(to,x);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<=low[to])
                {
                    src_cnt++,posi[x]++;
                    int t=0;
                    while(top!=pre)
                    {
                        t=my_stack[top--];
                        peo[src_cnt].push_back(t);
                    }
                    peo[src_cnt].push_back(x);
                    sort(peo[src_cnt].begin(),peo[src_cnt].end());
                }
            }else low[x]=min(low[x],dfn[to]);
        }
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void min_dis_spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    void max_dis_spfa(int st)
    {
        memset(dis,0,sizeof(dis));
        used[st]=1;
        dis[st]=src_num[st];
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=0;i<v[u].size();i++)
            {
                int to=v[u][i];
                if(dis[to]<dis[u]+src_num[to])
                {
                    dis[to]=dis[u]+src_num[to];
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        ll ans=0;
        for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
        printf("%lld
    ",ans);
    }
    void build_MST()
    {
        kruscal();
    }
    void get_min_dis_road()
    {
        //min_dis_spfa(S);
        diji(S);
    }
    void solve_LCA()
    {
        tree_dfs(S,S),tree_redfs(S,S,S);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            printf("%d
    ",link_cut_LCA(x,y));
        }
    }
    void direc_tarjan()//有向图tarjan
    {
        for(int i=1;i<=n;i++)read(va[i]);
        read(S),read(nu);
        for(int i=1;i<=nu;i++)read(spe[i]);
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]==posi[to])continue;
                else v[posi[i]].push_back(posi[to]);
            }
        }
        max_dis_spfa(posi[S]);
    }
    void cut_line_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
        printf("%d ",count_cut_line);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]!=posi[to])inr[posi[to]]++;
            }
        }
        int s=0;
        for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
        printf("%d
    ",(s+1)>>1);
    }
    void cut_point_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
        for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
        printf("%d
    ",cut_point.size());
        for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
        printf("
    ");
        printf("%d
    ",src_cnt);
        sort(peo+1,peo+src_cnt+1,cmp);
        for(int i=1;i<=src_cnt;i++,printf("
    "))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
    }
    int ide(int x)
    {
        return x&1?x+1:x-1;
    }
    bool dinic_bfs()
    {
        memset(dis,0,sizeof(dis));
        memcpy(cur,head,sizeof(head));
        dis[S]=1;
        queue <int> M;
        M.push(S);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
            }
        }
        return dis[T];
    }
    ll dinic_dfs(int x,ll lim)
    {
        if(x==T)return lim;
        ll ret=0;
        for(int i=cur[x];i;i=edge[i].nxt)
        {
            cur[x]=i;
            int to=edge[i].to;
            if(edge[i].val&&dis[to]==dis[x]+1)
            {
                ll temp=dinic_dfs(to,min(lim,edge[i].val));
                if(temp)
                {
                    ret+=temp,lim-=temp;
                    edge[i].val-=temp,edge[ide(i)].val+=temp;
                    if(!lim)break;
                }
            }
        }
        return ret;
    }
    ll dinic()
    {
        ll ans=0;
        while(dinic_bfs())ans+=dinic_dfs(S,INF);
        return ans;
    }
    void max_flow()
    {
        printf("%lld
    ",dinic());
    }
    bool EK_spfa()
    {
        memset(pre,-1,sizeof(pre));
        memset(f,0,sizeof(f));
        memset(dis,0x3f,sizeof(dis));
        dis[S]=0,lim[S]=INF,used[S]=1;
        queue <int> M;
        M.push(S);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
                {
                    dis[to]=dis[u]+edge[i].pri;
                    pre[to]=i,f[to]=u,lim[to]=min(lim[u],edge[i].val);
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        return pre[T]!=-1;
    }
    void EK()
    {
        ll maxf=0,minv=0;
        while(EK_spfa())
        {
            maxf+=lim[T],minv+=dis[T]*lim[T];
            int temp=T;
            while(temp!=S)edge[pre[temp]].val-=lim[T],edge[ide(pre[temp])].val+=lim[T],temp=f[temp];
        }
        printf("%lld %lld
    ",maxf,minv);
    }
    void min_cost_max_flow()
    {
        S=1,T=n;
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z,w;
            read(x),read(y),read(z),read(w);
            cost_dadd(x,y,z,w);
        }
        EK();
    }
    void two_SAT()
    {
        for(int i=1;i<=m;i++)
        {
            int x,y,z,w;
            read(x),read(y),read(z),read(w);
            if(y==1&&w==1)add(x+n,z,0),add(z+n,x,0);
            else if(y==1)add(x+n,z+n,0),add(z,x,0);
            else if(w==1)add(x,z,0),add(z+n,x+n,0);
            else add(x,z+n,0),add(z,x+n,0);
        }
        n<<=1;
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        n>>=1;
        for(int i=1;i<=n;i++)if(posi[i]==posi[i+n]){printf("IMPOSSIBLE
    ");exit(0);}
        printf("POSSIBLE
    ");
        for(int i=1;i<=n;i++)
        {
            if(posi[i]<posi[i+n])printf("1 ");
            else printf("0 ");
        }
        printf("
    ");
    }
    int main()
    {
        read(n),read(m)//,read(S),read(T);
        init();
        two_SAT();
        return 0;
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z;
            read(x),read(y),read(z);
            dadd(x,y,z);//,add(y,x,z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        return 0;
    }

    7.二分图匹配(匈牙利)

    #include <cstdio>
    #include <cmath>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <vector>
    #define ll long long
    using namespace std;
    const int maxn=2000005;
    const int maxm=5000005;
    template <typename T>inline void read(T &x)
    {
        T f=1,c=0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x=c*f;
    }
    const int inf=0x3f3f3f3f;
    const ll INF=0x3f3f3f3f3f3f3f3fll;
    struct Edge
    {
        int nxt;
        int to;
        ll val;
        ll pri;
    }edge[maxm];
    struct E
    {
        int l,r;
        ll v;
        friend bool operator < (E a,E b)
        {
            return a.v<b.v;
        }
    }e[maxm];
    struct node
    {
        int p;ll v;
        node (){}
        node (int x,ll y):p(x),v(y){}
        friend bool operator < (node a,node b)
        {
            return a.v>b.v;
        }
    };
    int f[maxn];
    int head[maxn];
    ll dis[maxn];
    ll va[maxn];
    int dfn[maxn],low[maxn],posi[maxn];
    ll src_num[maxn],src_cnt;
    int my_stack[maxn],top=0;
    int fa[maxn][25];
    int dep[maxn];
    int spe[maxn],nu;
    int siz[maxn],son[maxn],ttop[maxn];
    int inr[maxn],our[maxn];
    int cur[maxn];
    int pre[maxn];
    ll lim[maxn];
    bool used[maxn];
    int cnt=1,deep;
    int count_cut_line;
    int n,m,S,T;
    vector <int> v[maxn];
    vector <int> peo[maxn];
    vector <int> cut_point;
    bool cmp(vector <int> a,vector <int> b)
    {
        int lim=min(a.size(),b.size());
        for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
        return a.size()<b.size();
    }
    void init()
    {
        //for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
        cnt=1;
    }
    void add(int l,int r,ll w)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        head[l]=cnt++;
    }
    void dadd(int l,int r,int w)
    {
        add(l,r,w),add(r,l,0);
    }
    void cost_add(int l,int r,ll w,ll p)
    {
        edge[cnt].nxt=head[l];
        edge[cnt].to=r;
        edge[cnt].val=w;
        edge[cnt].pri=p;
        head[l]=cnt++;
    }
    void cost_dadd(int l,int r,ll w,ll p)
    {
        cost_add(l,r,w,p),cost_add(r,l,0,-p);
    }
    int findf(int x)
    {
        return x==f[x]?x:f[x]=findf(f[x]);
    }
    void tree_dfs(int x,int fx)
    {
        dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
        for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            tree_dfs(to,x);
            siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
        }
    }
    void tree_redfs(int x,int topx,int fx)
    {
        ttop[x]=topx;
        if(son[x])tree_redfs(son[x],topx,x);
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx||to==son[x])continue;
            tree_redfs(to,to,x);
        }
    }
    int quick_jump_LCA(int x,int y)//倍增LCA
    {
        if(dep[x]>dep[y])swap(x,y);
        for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
        if(x==y)return x;
        int ret;
        for(int i=20;i>=0;i--)
        {
            if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
            else ret=fa[x][i]; 
        }
        return ret;
    }
    int link_cut_LCA(int x,int y)//树剖LCA
    {
        while(ttop[x]!=ttop[y])
        {
            if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
            x=fa[ttop[x]][0];
        }
        return dep[x]<dep[y]?x:y;
    }
    void di_tarjan(int x)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(!dfn[to])
            {
                di_tarjan(to);
                low[x]=min(low[x],low[to]);
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void ed_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(edge[i].val==fx)continue;
            if(!dfn[to])
            {
                ed_tarjan(to,edge[i].val);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<low[to])count_cut_line++;
            }else if(!posi[to])low[x]=min(low[x],dfn[to]);
        }
        if(dfn[x]==low[x])
        {
            src_cnt++;
            int t=0;
            while(t!=x)
            {
                t=my_stack[top--];
                src_num[src_cnt]++;
                posi[t]=src_cnt;
            }
        }
    }
    void po_tarjan(int x,int fx)
    {
        my_stack[++top]=x,dfn[x]=low[x]=++deep;
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(to==fx)continue;
            if(!dfn[to])
            {
                int pre=top;
                po_tarjan(to,x);
                low[x]=min(low[x],low[to]);
                if(dfn[x]<=low[to])
                {
                    src_cnt++,posi[x]++;
                    int t=0;
                    while(top!=pre)
                    {
                        t=my_stack[top--];
                        peo[src_cnt].push_back(t);
                    }
                    peo[src_cnt].push_back(x);
                    sort(peo[src_cnt].begin(),peo[src_cnt].end());
                }
            }else low[x]=min(low[x],dfn[to]);
        }
    }
    void kruscal()
    {
        sort(e+1,e+m+1);
        int tot=0;ll ret=0;
        for(int i=1;i<=m;i++)
        {
            int f1=findf(e[i].l),f2=findf(e[i].r);
            if(f1==f2)continue;
            f[f1]=f2,tot++,ret+=e[i].v;
            if(tot==n-1)break;
        }
        if(tot==n-1)printf("%lld
    ",ret);
        else printf("orz
    ");
    }
    void min_dis_spfa(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0,used[st]=1;
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val)
                {
                    dis[to]=dis[u]+edge[i].val;
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        for(int i=1;i<=n;i++)
        {
            if(dis[i]==INF)printf("2147483647 ");
            else printf("%lld ",dis[i]);
        }
    }
    void diji(int st)
    {
        memset(dis,0x3f,sizeof(dis));
        dis[st]=0;
        priority_queue <node> M;
        M.push(node(st,0));
        while(!M.empty())
        {
            node temp=M.top();
            M.pop();
            int u=temp.p;
            if(used[u])continue;
            used[u]=1;
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
            }
        }
        for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
    }
    void max_dis_spfa(int st)
    {
        memset(dis,0,sizeof(dis));
        used[st]=1;
        dis[st]=src_num[st];
        queue <int> M;
        M.push(st);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=0;i<v[u].size();i++)
            {
                int to=v[u][i];
                if(dis[to]<dis[u]+src_num[to])
                {
                    dis[to]=dis[u]+src_num[to];
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        ll ans=0;
        for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
        printf("%lld
    ",ans);
    }
    void build_MST()
    {
        kruscal();
    }
    void get_min_dis_road()
    {
        //min_dis_spfa(S);
        diji(S);
    }
    void solve_LCA()
    {
        tree_dfs(S,S),tree_redfs(S,S,S);
        for(int i=1;i<=m;i++)
        {
            int x,y;
            read(x),read(y);
            printf("%d
    ",link_cut_LCA(x,y));
        }
    }
    void direc_tarjan()//有向图tarjan
    {
        for(int i=1;i<=n;i++)read(va[i]);
        read(S),read(nu);
        for(int i=1;i<=nu;i++)read(spe[i]);
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]==posi[to])continue;
                else v[posi[i]].push_back(posi[to]);
            }
        }
        max_dis_spfa(posi[S]);
    }
    void cut_line_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
        printf("%d ",count_cut_line);
        for(int i=1;i<=n;i++)
        {
            for(int j=head[i];j;j=edge[j].nxt)
            {
                int to=edge[j].to;
                if(posi[i]!=posi[to])inr[posi[to]]++;
            }
        }
        int s=0;
        for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
        printf("%d
    ",(s+1)>>1);
    }
    void cut_point_tarjan()
    {
        for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
        for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
        printf("%d
    ",cut_point.size());
        for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
        printf("
    ");
        printf("%d
    ",src_cnt);
        sort(peo+1,peo+src_cnt+1,cmp);
        for(int i=1;i<=src_cnt;i++,printf("
    "))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
    }
    int ide(int x)
    {
        return x&1?x+1:x-1;
    }
    bool dinic_bfs()
    {
        memset(dis,0,sizeof(dis));
        memcpy(cur,head,sizeof(head));
        dis[S]=1;
        queue <int> M;
        M.push(S);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
            }
        }
        return dis[T];
    }
    ll dinic_dfs(int x,ll lim)
    {
        if(x==T)return lim;
        ll ret=0;
        for(int i=cur[x];i;i=edge[i].nxt)
        {
            cur[x]=i;
            int to=edge[i].to;
            if(edge[i].val&&dis[to]==dis[x]+1)
            {
                ll temp=dinic_dfs(to,min(lim,edge[i].val));
                if(temp)
                {
                    ret+=temp,lim-=temp;
                    edge[i].val-=temp,edge[ide(i)].val+=temp;
                    if(!lim)break;
                }
            }
        }
        return ret;
    }
    ll dinic()
    {
        ll ans=0;
        while(dinic_bfs())ans+=dinic_dfs(S,INF);
        return ans;
    }
    void max_flow()
    {
        printf("%lld
    ",dinic());
    }
    bool EK_spfa()
    {
        memset(pre,-1,sizeof(pre));
        memset(f,0,sizeof(f));
        memset(dis,0x3f,sizeof(dis));
        dis[S]=0,lim[S]=INF,used[S]=1;
        queue <int> M;
        M.push(S);
        while(!M.empty())
        {
            int u=M.front();
            M.pop();
            for(int i=head[u];i;i=edge[i].nxt)
            {
                int to=edge[i].to;
                if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
                {
                    dis[to]=dis[u]+edge[i].pri;
                    pre[to]=i,f[to]=u,lim[to]=min(lim[u],edge[i].val);
                    if(!used[to])used[to]=1,M.push(to);
                }
            }
            used[u]=0;
        }
        return pre[T]!=-1;
    }
    void EK()
    {
        ll maxf=0,minv=0;
        while(EK_spfa())
        {
            maxf+=lim[T],minv+=dis[T]*lim[T];
            int temp=T;
            while(temp!=S)edge[pre[temp]].val-=lim[T],edge[ide(pre[temp])].val+=lim[T],temp=f[temp];
        }
        printf("%lld %lld
    ",maxf,minv);
    }
    void min_cost_max_flow()
    {
        S=1,T=n;
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z,w;
            read(x),read(y),read(z),read(w);
            cost_dadd(x,y,z,w);
        }
        EK();
    }
    void two_SAT()
    {
        for(int i=1;i<=m;i++)
        {
            int x,y,z,w;
            read(x),read(y),read(z),read(w);
            if(y==1&&w==1)add(x+n,z,0),add(z+n,x,0);
            else if(y==1)add(x+n,z+n,0),add(z,x,0);
            else if(w==1)add(x,z,0),add(z+n,x+n,0);
            else add(x,z+n,0),add(z,x+n,0);
        }
        n<<=1;
        for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
        n>>=1;
        for(int i=1;i<=n;i++)if(posi[i]==posi[i+n]){printf("IMPOSSIBLE
    ");exit(0);}
        printf("POSSIBLE
    ");
        for(int i=1;i<=n;i++)
        {
            if(posi[i]<posi[i+n])printf("1 ");
            else printf("0 ");
        }
        printf("
    ");
    }
    bool dfs(int x)
    {
        for(int i=head[x];i;i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(used[to])continue;
            used[to]=1;
            if(!f[to]||dfs(f[to])){f[to]=x;return 1;}
        }
        return 0;
    }
    int hungary()
    {
        int ret=0;
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n+m;j++)used[j]=0;
            if(dfs(i))ret++;
        }
        return ret;
    }
    void two_match()
    {
        read(n),read(m),read(S);
        for(int i=1;i<=S;i++)
        {
            int x,y;
            read(x),read(y);
            if(x>n||y>m)continue;
            add(x,y+n,0),add(y+n,x,0);
        }
        printf("%d
    ",hungary());
    }
    int main()
    {
        two_match();
        return 0;
        read(n),read(m);//,read(S),read(T);
        init();
        for(int i=1;i<=m;i++)
        {
            int x,y;ll z;
            read(x),read(y),read(z);
            dadd(x,y,z);//,add(y,x,z);
            e[i].l=x,e[i].r=y,e[i].v=z;
        }
        return 0;
    }
  • 相关阅读:
    关于MySQL死锁
    随手一记,maven打包
    js生成带logo的二维码
    java生成带logo的二维码
    关于网页中文本域高度自动适应问题,参考微信回复
    从git上拉下来的严选weex项目demo
    补装老版本的Java SE
    新MBP使用git命令时启用xcode的终端log
    电脑出现“损坏的图像”窗口提示dll没有被指定在Windows上运行如何解决
    不同浏览器隐藏默认表单样式
  • 原文地址:https://www.cnblogs.com/zhangleo/p/11174957.html
Copyright © 2011-2022 走看看