`
yzmduncan
  • 浏览: 331898 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

最多不相交路径

阅读更多

    最长上升子序列是一个经典问题,可以用O(n^2)的dp解决。给出一个串,求出最长上升子序列的长度为多少?假设长度为s,现在问题是,有多少个长度为s的上升子序列,满足每个子序列所包含的元素均不相同(即一个数只能选一次)。

    建模:

    第一问直接用dp求解,dp[i]表示以i为结尾的最长递增子序列的长度,最后取dp[1~n]的最大值,即为s。

    第二问可以利用上一问求出来的dp数组,用网络流求解。

    1. 拆点,将每个点拆成两点,容量为1,保证每个点只取一次。

    2. 增加源点s和汇点t,s和dp[i]=1的点相连,dp[i]=s的点和t相连,容量均为INF。

    3. 对于两点i和j(j<i),如果满足条件:a[j]<a[i]&&dp[j]+1=dp[i],添加有向边(j,i),容量为INF。

    这样,保证从s到t的每一条路都是一条最长递增子序列,最大流即为答案。

   例:HDU3998

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int INF = 0x7fffffff;
const int maxv = 2000;
const int maxe = maxv*maxv*2;
int n,s;
int a[maxv];
int dp[maxv];
int source,sink;
//
struct Edge
{
    int v;
    int next;
    int flow;
};
Edge e[maxe];
int head[maxv],edgeNum;
int now[maxv],d[maxv],vh[maxv],pre[maxv],preh[maxv];

void addEdge(int a,int b,int c)
{
    e[edgeNum].v = b;
    e[edgeNum].flow = c;
    e[edgeNum].next = head[a];
    head[a] = edgeNum++;
    e[edgeNum].v = a;
    e[edgeNum].flow = 0;
    e[edgeNum].next = head[b];
    head[b] = edgeNum++;
}

void Init()
{
    edgeNum = 0;
    memset(head,-1,sizeof(head));
    memset(d,0,sizeof(d));
}

int sap(int s,int t,int n)       //源点,汇点,结点总数
{
    int i,x,y;
    int f,ans = 0;
    for(i = 0; i < n; i++)
        now[i] = head[i];
    vh[0] = n;
    x = s;
    while(d[s] < n)
    {
        for(i = now[x]; i != -1; i = e[i].next)
            if(e[i].flow > 0 && d[y=e[i].v] + 1 == d[x])
                break;
            if(i != -1)
            {
                now[x] = preh[y] = i;
                pre[y] = x;
                if((x=y) == t)
                {
                    for(f = INF,i=t; i != s; i = pre[i])
                        if(e[preh[i]].flow < f)
                            f = e[preh[i]].flow;
                    ans += f;
                    do
                    {
                        e[preh[x]].flow -= f;
                        e[preh[x]^1].flow += f;
                        x = pre[x];
                    }while(x!=s);
                }
            }
            else
            {
                if(!--vh[d[x]])
                    break;
                d[x] = n;
                for(i=now[x]=head[x]; i != -1; i = e[i].next)
                {
                    if(e[i].flow > 0 && d[x] > d[e[i].v] + 1)
                    {
                        now[x] = i;
                        d[x] = d[e[i].v] + 1;
                    }
                }
                ++vh[d[x]];
                if(x != s)
                    x = pre[x];
            }
    }
    return ans;
}
//

void build()
{
    int i,j;
    Init();
    source = 0;
    sink = 2*n+1;
    for(i = 1; i <= n; i++)
        addEdge(i,i+n,1);
    for(i = 1; i <= n; i++)
    {
        if(dp[i]==1)
            addEdge(source,i,INF);
        if(dp[i]==s)
            addEdge(i+n,sink,INF);
    }
    for(i = 1; i <= n; i++)
    {
        for(j = 1; j < i; j++)
        {
            if(a[j] < a[i] && dp[j]+1 == dp[i])
                addEdge(j+n,i,INF);
        }
    }
}

int main()
{
    int i,j;
    while(scanf("%d",&n)!=EOF)
    {
        s = -1;
        for(i = 1; i <= n; i++)
            scanf("%d",&a[i]);
        for(i = 1; i <= n; i++)
            dp[i] = 1;
        for(i = 1; i <= n; i++)
        {
            for(j = 1; j < i; j++)
            {
                if(a[j] < a[i] && dp[j] + 1 > dp[i])
                    dp[i] = dp[j] + 1;
            }
        }
        for(i = 1; i <= n; i++)
        {
            if(s < dp[i])
                s = dp[i];
        }
        printf("%d\n",s);
        build();
        printf("%d\n",sap(source,sink,sink+1));
    }
    return 0;
}

 

 

分享到:
评论

相关推荐

    线性规划与网络流题解

    6 最长递增子序列问题 最多不相交路径 网络最大流 7 试题库问题 二分图多重匹配 网络最大流 8 机器人路径规划问题 (未解决) 最小费用最大流 9 方格取数问题 二分图点权最大独立集 网络最小割 10 餐巾计划问题 线性...

    无向图中边不相交Min-Min问题的复杂度 (2012年)

    再给定两个不同的顶点\(s, t \in V\)以及一个长度函数\(l: E \rightarrow \mathbb{R}^+\),任务是找到一对顶点不相交的路径\(AP\)(活跃路径)和\(BP\)(备份路径),使得较短路径的长度\(l(AP)\)最小化,其中\(l(AP...

    NP完全性证明举例1

    因此,G中的一个独立集S={i1, i2, ..., it}对应于G*中的一组不相交路径Pi1, Pi2, ..., Pit。 这个归约过程可以在多项式时间内完成,因为它涉及到简单的图操作和路径构造。如果能找到k条不相交的路径,那么原始图G就...

    分治算法在树的路径问题中的应用.ppt

    - 选取一条边将原树分成两棵不相交的树。 - 分别对这两棵树递归处理。 - 最坏情况下,递归次数可能达到O(N)。 ### 例一:树中点对统计 给定一棵有N个节点的带权树,定义节点u和v之间的距离`dist(u, v)`为从u到v...

    算法合集之分治算法在树的路径问题中的应用PPT学习教案.pptx

    基于边的分治方法则是选取树中的一条边,将树分割成两棵不相交的子树,然后递归处理这两部分。这种方法在最坏情况下可能会导致O(N)次的递归调用。 ### 二、树的路径剖分算法 路径剖分算法主要用于高效地处理树的...

    20151910042-刘鹏-AG实验06-有向图的弧连通度1

    Menger定理的两个推论分别讨论了在无向图中找到不相交路径的边截集和点截集版本。 在有向图中,寻找弧连通度通常涉及使用网络流算法,例如Edmonds-Karp算法。这是因为网络流算法可以用来寻找两个指定顶点间最大流量...

    七年级数学下新思维第一讲 相交线与平行线.doc

    1. 平面内直线的交点公式表明,n条直线相交最多会产生个交点。例如,平面内的四条直线可能有0至6个交点,具体取决于它们的位置关系。 2. 直线相交可以将平面分割成多个部分,n条直线最多可分区块,可以通过递推公式1...

    四年级数学上册 第四单元 交通中的线 平行与相交测试题(无答案) 青岛版 试题.doc

    1. 在同一平面内,不相交的两条直线是平行的,答案为B。 2. 通过直线外一点只能画一条与已知直线平行的线,答案为A。 3. 通过一点可以画无数条直线,通过两点可以画一条直线,答案分别是C和A。 4. 同一平面内的两条...

    游戏连连看设计思路让每个爱玩游戏的人感觉到快乐

    3. **路径**:由一条或多条直线构成,但在连连看游戏中,最多允许不超过三条直线来连接两个基点。 接下来,我们来看连连看的具体设计思路: 1. **选择基点**:当玩家点击两个相同的图片时,确定它们的基点P1和P2。...

    二分图匹配算法总结1

    此外,最小路径覆盖问题是在有向无环图中寻找最少数目的不相交简单路径以覆盖所有节点,可以通过构建二分图模型并利用最大匹配来解决。 最大独立集问题是在图G中找到最大的点子集,其中任意两点之间没有边。在二分...

    康奈尔 CS6820 算法分析讲义

    - **二分图**:由两个不相交的顶点集\(U\)和\(V\)以及连接这两个集合中顶点的边集\(E\)组成,其中每条边的一端位于\(U\)中,另一端位于\(V\)中。 - **匹配**:在无向图中,一个匹配是一组边,使得没有顶点属于该组的...

    算法学习:图论之用匈牙利算法求二分图的最大匹配.doc

    - 路径上的边交替地不在当前匹配中与在当前匹配中。 - 路径的起点和终点是没有被匹配的节点。 #### 四、匈牙利算法的具体步骤 1. **初始化**:将当前最大匹配设置为空。 2. **循环执行**: - 寻找一条增广路径。...

    匈牙利算法及常见建图模型

    在二分图中,顶点集可以被分为两个互不相交的子集,边则连接这两个子集中的顶点。二分图的最大匹配是指在不违反匹配规则(即两个顶点不能同时与同一边关联)的前提下,找到包含尽可能多边的子集。 在描述中的两个...

    二分图及其应用(ACM 算法)

    二分图的最大匹配问题是寻找二分图中最多的一对对顶点,使得每对顶点之间有一条边相连,且任意两对顶点间的边不相交。这个问题在实际中有多种应用,比如婚姻匹配、作业分配、网络路由等。 匈牙利算法是解决二分图...

    平面设计师考试题.pdf

    2. **PathFinder(路径寻找器)**:该工具提供了一组操作来合并、相交、挖空和拆分图形。例如,"Unite"(交集)将多个路径合并为一个单一对象,"Merge"(并集)将重叠部分合并,"Offset Path"(偏移路径)创建路径的...

    Detecting a network failure

    他们的分析在图分离器和VC维(Vapnik–Chervonenkis维数)的概念之间建立了一种联系,利用了基于匹配和不相交路径的技术。 研究论文的引言部分讨论了在大型未结构化网络中推断网络属性的困难。基本问题包括:网络的...

    目标跟踪系列-匹配-1. 匈牙利&KM匹配算法

    二分图是由两个不相交的顶点集合构成,它们之间的边不相连。最大匹配指的是在二分图中找到数量最多的边,这些边之间没有公共端点。如果每个顶点都能与一条边相关联,那么就形成了一个完美匹配,也就是完备匹配。 ...

    二分匹配与匈牙利算法

    3. 重复步骤2,直到找不到增广路径。 在实际编程中,可以使用队列数据结构来实现这一过程。 当图的边带有权重时,我们关注的是找到权值之和最大的匹配,这被称为最佳匹配。例如,在职员与工作任务分配的问题中,每...

    33-图算法-最大二分匹配1

    二分图的最大匹配是指在保持所有匹配边不相交的情况下,尽可能多地找到图中的匹配。在打车难的问题中,可以将乘客视为一个集合,司机视为另一个集合,每条边代表一个乘客可能被一个司机接载的情况。最大二分匹配的...

Global site tag (gtag.js) - Google Analytics