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;
}
原文地址:https://www.cnblogs.com/zhangleo/p/11174957.html