hb的lj图论模板(自用)

  • 最小生成树堆优化prim算法·
  • #include<iostream>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    int n,m,cnt,head[100010],dis[100010],sum,vis[100010],k;
    
    struct data{
        int next;
        int to;
        int dis;
    }e[400010];
    
    void add(int u,int v,int w){
        cnt++;
        e[cnt].dis=w;
        e[cnt].to=v;
        e[cnt].next=head[u];
        head[u]=cnt;
    }
    
    typedef pair <int,int> pii;
    priority_queue <pii,vector<pii>,greater<pii> > q;
    
    void prim(int s){
        dis[s]=0;
        q.push(make_pair(0,s));
        while(!q.empty()&&k<n){
            int d=q.top().first;
            int u=q.top().second;
            q.pop();
            if(vis[u]) continue;
            k++;
            sum+=d;
            vis[u]=1;
            for(register int i=head[u];i!=-1;i=e[i].next){
                if(e[i].dis<dis[e[i].to]){
                    dis[e[i].to]=e[i].dis;
                    q.push(make_pair(dis[e[i].to],e[i].to));
                }
            }
        }
    }
    
    int main(){
        int x,y,z;
        memset(dis,127,sizeof(dis));
        memset(head,-1,sizeof(head));
        cin>>n>>m;
        for(register int i=1;i<=m;i++){
            cin>>x>>y>>z;
            add(x,y,z);
            add(y,x,z);
        }
        prim(1);
        if(k==n)
            cout<<sum;
        else
            cout<<"orz";
        return 0;
    }

    最小生成树kruscal

  • #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    
    using namespace std;
    
    const int M=200010;
    
    inline int read(){
        int x=0;bool f=1; char c=getchar();
        while(!isdigit(c)){if(c=='-')f=0;c=getchar();}
        while(isdigit(c)){x=x*10+c-'0';c=getchar();}
        if(!f)return 0-x;
        return x;
    }
    
    struct data{
        int u,v,w;
    }e[M*2];
    
    int n,cnt,m,fa[M],c,ans;
    
    bool cmp(data a,data b){
        return a.w<b.w;
    }
    
    int find(int x){
        if(fa[x]==x)return x;
        return fa[x]=find(fa[x]);
    }
    
    void kruskal(){
        sort(e+1,e+1+m,cmp);
        for(int i=1;i<=m;i++){
            int v=e[i].v;int u=e[i].u;int d=e[i].w;
            int fv=find(v);int fu=find(u);
            if(fv==fu)continue;
            ans+=d;
            fa[fv]=fu;
            c++;
            if(c==n-1)break;
        }
    }
    
    int main(){
        freopen("haha.in","r",stdin);
        n=read(),m=read();
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++){
            int x,y,z;
            x=read(),y=read(),z=read();
            e[i].u=x,e[i].v=y,e[i].w=z;
        }
        kruskal();
        if(c!=n-1)cout<<"orz";
        else cout<<ans;
        fclose(stdin);
        return 0;
    }

    单元最短路spfa

  • #include<iostream>
    #include<queue>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    struct data{
        int to;
        int dis;
        int next;
    }e[500010];
    
    int n,m,head[500010],cnt,vis[500010],dis[500010];
    
    void add(int u,int v,int w){
        cnt++;
        e[cnt].to=v;
        e[cnt].dis=w;
        e[cnt].next=head[u];
        head[u]=cnt;
    }
    
    //void pre(int s){
    //    for(int i=head[s];i!=-1;i=e[i].next){
    //        int v=e[i].to;
    //        int ww=e[i].dis;
    //        dis[v]=min(dis[v],ww);
    //    }
    //    dis[s]=0;
    //}
    
    void spfa(int s){
        queue<int>q;
    //    pre(s);
        dis[s]=0;
        q.push(s);
        vis[s]=1;
        while(!q.empty()){
            int u=q.front();
            q.pop();
            vis[u]=0;
            for(int i=head[u];i!=-1;i=e[i].next){
                int v=e[i].to;
                if(dis[v]>dis[u]+e[i].dis){
                    dis[v]=dis[u]+e[i].dis;
                    if(vis[v]!=1){
                        q.push(v);
                        vis[v]=1;
                    }
                }
            }
        }
    }
    
    int main(){
    //    freopen("haha.in","r",stdin);
        memset(head,-1,sizeof(head));
        int s,u,v,w;
        cin>>n>>m>>s;
        for(int i=1;i<=n;i++){
            dis[i]=2147483647;
        }
        for(int i=1;i<=m;i++){
            cin>>u>>v>>w;
            add(u,v,w);
            
        }
        spfa(s);
        for(int i=1;i<=n;i++){
            cout<<dis[i]<<' ';
        }
    //    fclose(stdin);
        return 0;
    }

    并查集

  • #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    inline int read(){
        int x=0; bool f=1; char c=getchar();
        while(!isdigit(c)){if(c=='-')f=0;c=getchar();}
        while(isdigit(c)){x=x*10+c-'0';c=getchar();}
        if(!f)return 0-x;
        return x;
    }
    
    int n,m;
    int fa[10010];
    
    int findfa(int x){
        if(fa[x]==x)return x;
        fa[x]=findfa(fa[x]);
        return fa[x];
    }
    
    void join(int x,int y){
        int fx=findfa(x);
        int fy=findfa(y);
        if(fx!=fy){
            fa[fx]=fy;
        }
    }
    
    int main(){
    //    freopen("haha.in","r",stdin);
        int x,y,z;
        n=read(),m=read();
        for(int i=1;i<=n;i++){
            fa[i]=i;
        }
        while(m>0){
            m--;
            x=read();
            y=read();
            z=read();
            if(x==1){
                join(y,z);
            }
            if(x==2){
                if(findfa(y)==findfa(z))cout<<"Y"<<endl;
                else cout<<"N"<<endl;
            }
        }
    //    fclose(stdin);
        return 0;
    }

    强连通分量

  • #include<iostream>
    #include<queue>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
    #include<cstring>
    
    using namespace std;
    
    vector<int>g[10010];
    
    int color[10010],dfn[20020],low[20020],stack[20020],vis[10010],cnt[10010];
    int deep,top,n,m,sum,ans;
    
    void tarjan(int u){
        dfn[u]=low[u]=++deep;
        vis[u]=1;
        stack[++top]=u;
        int sz=g[u].size();
        for(int i=0;i<sz;i++){
            int v=g[u][i];
            if(!dfn[v]){
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else{
                if(vis[v]){
                    low[u]=min(low[u],low[v]);
                }
            }
        }
        if(dfn[u]==low[u]){
            color[u]=++sum;
            vis[u]=0;
            while(stack[top]!=u){
                color[stack[top]]=sum;
                vis[stack[top--]]=0;
            }
            top--;
        }
    }
    
    int main(){
        cin>>n>>m;
        while(m>0){
            m--;
            int a,b;
            cin>>a>>b;
            g[a].push_back(b);
        }
        for(int i=1;i<=n;i++){
            if(!dfn[i])
                tarjan(i);
        }
        for(int i=1;i<=n;i++){
            cnt[color[i]]++;
        }
        for(int i=1;i<=sum;i++){
            if(cnt[i]>1)
                ans++;
        }
        cout<<ans;
    }

    割点

  • #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    const int M=20005;
    
    vector<int>e[M];
    
    int dfn[M],vis[M],low[M],parent[M],ap[M],cnt,r[M],countt,fa[M],tu=1;
    
    struct data{
        int num;
        int book;
    }z[M];
    
    int find(int x){
        if(fa[x]==x)return x;
        else return fa[x]=find(fa[x]);
    }
    
    void join(int x,int y){
        int fx=find(x);
        int fy=find(y);
        if(fx!=fy){
            fa[fx]=fy;
        }
    }
    void tarjan(int u){
        int children=0;
        dfn[u]=low[u]=countt++;
        vis[u]=1;
        for(int i=0;i<e[u].size();i++){
            int v=e[u][i];
            if(!vis[v]){
                children++;
                parent[v]=u;
                tarjan(v);
                low[u]=min(low[u],low[v]);
                if(parent[u]==-1&&children>=2){
                    cnt++;
                    r[cnt]=u;
                }
                else if(parent[u]!=-1&&low[v]>=dfn[u]){
                    cnt++;
                    r[cnt]=u;
                }
            }
            else if(v!=parent[u]){
                low[u]=min(low[u],dfn[v]);
            }
        }
    }
    
    int main(){
    //    freopen("haha.in","r",stdin);
        memset(parent,-1,sizeof(parent));
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            fa[i]=i;
        }
        for(int i=1;i<=m;i++){
            int x,y;
            cin>>x>>y;
            join(x,y);
            e[x].push_back(y);
            e[y].push_back(x);
        }
        z[tu].num=find(1);
        z[tu].book=1;
        for(int i=2;i<=n;i++){
            int t=find(i);
            int flag=0;
            for(int j=1;j<=tu;j++){
                if(t==z[j].num){
                    flag=1;
                }
            }
            if(flag==0){
                tu++;
                z[tu].num=t;
                z[tu].book=i;
            }
        }
        for(int i=1;i<=tu;i++)
        tarjan(z[i].book);
        int rp=cnt;
        sort(r+1,r+rp+1);
        for(int i=1;i<=rp;i++){
            if(r[i]==r[i-1]){
                cnt--;
            }
        }
        cout<<cnt<<endl;
        for(int i=1;i<=rp;i++){
            if(r[i]!=r[i-1])
            cout<<r[i]<<' ';
        }
    //    fclose(stdin);
        return 0;
    }

    拓扑排序

  • #include<iostream>
    #include<queue>
    #include<cstring>
    #include<cstdio>
    
    using namespace std;
    
    vector<int> e[10010];
    
    int indegree[10010];
    
    queue<int>ans;
    
    int suc=true,n;
    
    void topsort(){
        queue<int>q;
        while(1){
            for(int i=1;i<=n;i++){
                if(indegree[i]==0){
                    q.push(i);
                    ans.push(i);
                    indegree[i]=-1;
                }
            }
            if(q.empty())break;
            while(!q.empty()){
                int u=q.front();
                q.pop();
                for(int j=0;j<e[u].size();j++){
                    int v=e[u][j];
    //                if(indegree[v]==-1){
    //                    suc=false;
    //                    break;
    //                }
    //                else
                        indegree[v]--;
                }
                e[u].clear();
                if(!suc)break;
            }
            if(!suc)break;
        }
        if(ans.size()<n){
            suc=false;
            return ;
        }
    }
    
    void output(){
        bool isfirst=true;
        while(!ans.empty()){
            int t=ans.front();
            ans.pop();
            if(isfirst)
                cout<<t,isfirst=0;
            else
                cout<<' '<<t;
        }
        cout<<endl;
    }
    
    int main(){
        int m,a,b;
        cin>>n>>m;
        while(a!=0&&b!=0){
            cin>>a>>b;
            e[a].push_back(b);
            indegree[b]++;
        }
        topsort();
        if(suc)
        output();
        else
        cout<<"failed";
    }

    差分约束

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

using namespace std;

int cnt;

int head[10005],vis[10005],n,dis[10005];

struct data{
    int to;
    int dis;
    int next;
}e[10005];

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

void spfa(int s){
    queue<int>q;
    q.push(s);
    vis[s]=1;
    dis[s]=0;
    while(!q.empty()){
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].next){
            if(dis[e[i].to]<dis[u]+e[i].dis){
                dis[e[i].to]=dis[u]+e[i].dis;
                if(vis[e[i].to]==0){
                    vis[e[i].to]=1;
                    q.push(e[i].to);
                }
            }
        }
    }
    cout<<dis[n];
}

int main(){
//    freopen("haha.in","r",stdin);
    memset(dis,-63,sizeof(dis));
    memset(head,-1,sizeof(head));
    int m;
    cin>>m;
    for(int i=1;i<=m;i++){
        int x,y,z;
        cin>>x>>y>>z;
        add(x-1,y,z);
        n=max(n,y);
    }
    for(int i=1;i<=n;i++){
        add(i-1,i,0);
        add(i,i-1,-1);
    }
    spfa(0);
//    fclose(stdin);
    return 0;
}
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>

using namespace std;

inline int read(){
    int x=0; bool f=1; char c=getchar();
    while(!isdigit(c)){if(c=='-')f=0;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    if(!f)return 0-x;
    return x;
}

vector<int>g[1005];

int n,m,e,match[1005],ans,vis[1005];

bool dfs(int u){
    for(int i=0;i<g[u].size();i++){
        int v=g[u][i];
        if(!vis[v]){
            vis[v]=1;
            if(!match[v]||dfs(match[v])){
                match[v]=u;
                return true;
            }
        }
    }
    return false;
}

void solve(){
    for(int i=1;i<=n;i++){
        memset(vis,0,sizeof(vis));
        ans+=dfs(i);
    }
}

int main(){
//    freopen("haha.in","r",stdin);
    n=read(),m=read(),e=read();
    for(int i=1;i<=e;i++){
        int u,v;
        u=read(),v=read();
        if(v<=m&&u<=n){
            g[u].push_back(v);
//            g[v].push_back(u);
        }
    }
    solve();
    cout<<ans;
//    fclose(stdin);
    return 0;
}

  • 上面是二分图匹配
 
posted @ 2018-11-02 20:35  dahb3  阅读(9)  评论(0)    收藏  举报