zoukankan      html  css  js  c++  java
  • 图论模板集合

    二分图模板

    匈牙利算法 时间复杂度O(n^3)

    int n1,n2,k;
    
    //n1,n2为二分图的顶点集,其中x∈n1,y∈n2
    int map[N][N],vis[N],link[N];
    //link记录n2中的点y在n1中所匹配的x点的编号
    int find(int x)
    {
        int i;
        for(i=1;i<=n2;i++)
        {
            if(map[x][i]&&!vis[i])//x->i有边,且节点i未被搜索
            {
                vis[i]=1;//标记节点已被搜索
                //如果i不属于前一个匹配M或被i匹配到的节点可以寻找到增广路
                if(link[i]==0||find(link[i]))
                {
                    link[i]=x;//更新
                    return 1;//匹配成功
                }
            }        
        }
        return 0;
    }

    Hopcroft-Karp算法 时间复杂度O(n^0.5*e)

    讲解参照

    
    
    vector<int>ed[N];
    int xlink[N],ylink[N];/*xlink[i]表示左集合顶点所匹配的右集合顶点序号,ylink[i]表示右集合i顶点匹配到的左集合顶点序号。*/ 
    bool vis[N]; //寻找增广路的标记数组
    int dx[N],dy[N];/*dx[i]表示左集合i顶点的距离编号,dy[i]表示右集合i顶点的距离编号*/  
    int dis,n;
    void init()
    {
        memset(xlink,-1,sizeof(xlink));
        memset(ylink,-1,sizeof(ylink));
    }
    int bfs()
    {
        memset(dx,-1,sizeof(dx));
        memset(dy,-1,sizeof(dy));
        int i;
        queue<int>q;
        dis = INF;
        for(i = 1 ; i <= n;i++)
        if(xlink[i]==-1)
        {
            q.push(i);
            dx[i] = 0;
        }
        while(!q.empty())
        {
            int u = q.front(); q.pop();
            if(dx[u]>dis) break;
            for(i = 0 ;i < ed[u].size() ; i++)
            {
                int v = ed[u][i];
                if(dy[v]==-1)
                {
                    dy[v] = dx[u]+1;
                    if(ylink[v]==-1) dis = dy[v];
                    else
                    {
                        dx[ylink[v]] = dy[v]+1;
                        q.push(ylink[v]);
                    }
                }
            }
        }
        return dis!=INF;
    }
    int find(int u)
    {
        int i;
        for(i = 0;i < ed[u].size() ; i++)
        {
            int v = ed[u][i];
    
            if(vis[v]||dy[v]!=dx[u]+1) continue;
            vis[v] = 1;
            if(ylink[v] != -1&&dy[v]==dis) continue;
            if(ylink[v]==-1||find(ylink[v])) {
                ylink[v] = u;
                xlink[u] = v;
                return 1;
            }
        }
        return 0;
    }
    int hk()
    {
        int ans = 0,i;
        while(bfs())
        {
    
            memset(vis,0,sizeof(vis));
            for(i = 1 ; i <= n ;i++)
            {
                if(xlink[i]==-1)
                ans+=find(i);
            }
        }
        return ans;
    }

     最大流模板 

    Edmonds-Karp算法 时间复杂度O(n*e^2)

    int path[N],flow[N],gh[N][N],st,en;
    int bfs()
    {
        int i;
        memset(path,-1,sizeof(path));
        for(i = 1 ; i <= en ; i++)
        flow[i] = INF;
        queue<int>q;
        q.push(1);
        while(!q.empty())
        {
            int tk = q.front();
            q.pop();
            if(tk==en)
            break;
            for(i = 1 ; i <= en ; i++)
            {
                if(path[i]==-1&&gh[tk][i])
                {
                    path[i] = tk;
                    flow[i] = min(flow[tk],gh[tk][i]);
                    q.push(i);
                }
            }
        }
        if(path[en]==-1)
        return -1;
        return flow[en];
    }
    int km()
    {
        int now,pre,sum=0,k;
        while((k=bfs())!=-1)
        {
            sum+=k;
            now = en;
            while(now!=st)
            {
                pre = path[now];
                gh[pre][now]-=k;
                gh[now][pre]+=k;
                now = pre;
            }
        }
        return sum;
    }

     dinic算法 O(n*n*m)

    效率相对于上面快了很多

    #define INF 0x3f3f3f
    const int N = 415;
    #define M 160015
    struct node
    {
        int u,v,next;
        int w;
    } edge[M<<1];
    int head[N],t,vis[N],pp[N],dis[N];
    int o[N];
    int st,en;
    int x[N][N],f[N];
    void init()
    {
        t=0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v,int w)
    {
        edge[t].u = u;
        edge[t].v = v;
        edge[t].w = w;
        edge[t].next = head[u];
        head[u] = t++;
        edge[t].u = v;
        edge[t].v = u;
        edge[t].w = 0;
        edge[t].next = head[v];
        head[v] = t++;
    }
    int bfs()
    {
        int i,u;
        int w;
        memset(dis,-1,sizeof(dis));
        queue<int>q;
        q.push(st);
        dis[st] = 0;
        while(!q.empty())
        {
            u = q.front();
            q.pop();
            for(i = head[u] ; i != -1 ; i = edge[i].next)
            {
                int v = edge[i].v;
                w = edge[i].w;
                if(dis[v]<0&&w>0)
                {
                    dis[v] = dis[u]+1;
                    q.push(v);
                }
            }
        }
        if(dis[en]>0) return 1;
        return 0;
    }
    int dfs(int u,int te)
    {
        int i;
        int s;
        if(u==en) return te;
        for(i = head[u] ; i != -1 ; i = edge[i].next)
        {
            int v = edge[i].v;
            int w = edge[i].w;
            if(w>0&&dis[v]==dis[u]+1&&(s=dfs(v,min(te,w))))
            {
                edge[i].w-=s;
                edge[i^1].w+=s;
                return s;
            }
        }
        dis[u] = -1;
        return 0;
    }
    int dinic()
    {
        int flow = 0;
        int res;
        while(bfs())
        {
            while(res = dfs(st,INF))
            flow+=res;
        }
        return flow;
    }
  • 相关阅读:
    POJ 2175 Evacuation Plan 费用流 负圈定理
    POJ 2983 Is the Information Reliable? 差分约束
    codeforces 420B Online Meeting
    POJ 3181 Dollar Dayz DP
    POJ Ant Counting DP
    POJ 1742 Coins DP 01背包
    中国儒学史
    产品思维30讲
    Java多线程编程核心技术
    编写高质量代码:改善Java程序的151个建议
  • 原文地址:https://www.cnblogs.com/shangyu/p/3691981.html
Copyright © 2011-2022 走看看