• 有向环覆盖问题


    转载自这里

      给你一个N个顶点M条边的带权有向图,要你把该图分成一个或多个不相交的有向环。且所有定点都被有向环覆盖。问你该有向环所有权值的总和最小是多少?

      答案就是:有向环最大权值覆盖=最优匹配。

       如果,改为无向图,问你无向环最大权值覆盖?答案也是一样的。只是在建图的时候把有向改为无向即可。

    分析:

       我们把任意一个顶点i都分成两个,即i和i’. 如果原图存在i->j的边,那么二分图有i->j’的边.

           下面我们要引出几条结论:

            ① 如果原图能由多个不相交的有向环覆盖,那么二分图必然存在完备匹配。他们互为充要条件,也就是说如果二分图存在完备匹配,那么原图必定能由几个不想交的有向环覆盖. 

            ② 如果原图存在权值最大的有向环覆盖,那么二分图的最优匹配一定就是这个值。即权值最大的有向环覆盖在数值上等于改图的最优匹配值。

          因为该有向环覆盖对应了一个二分图的完备匹配,而该完备匹配的权值就等于该有向环覆盖的权值,所以最优匹配不可能丢失该最大权值的匹配。

      (假设原图的有向环为(1->2->3->1) and(6->5->4->6),那么二分图的完备匹配就是1->2’ 2->3’ 3->1’ 6->5’ 5->4’ 4->6’)

       (假设二分图的完备匹配是1->2’ 2->3’ 3->1’ 6->5’ 5->4’ 4->6’那么原图的有向环为(1->2->3->1) and (6->5->4->6))

    例如HDU1853:

           现在原题要求的是最小权匹配,我们把所有已知边的权值都取负数,且那些不存在的边我们取-INF(负无穷). 如果完备匹配存在,那么我们求出的最优匹配权值的绝对值 肯定<INF. 且该绝对值就是最小权值匹配.

           如果完备匹配不存在,那么最优匹配权值的绝对值肯定>INF.(想想是不是) 或者这么说,如果最终求得的匹配中,有任何一个匹配边用了权值为负无穷的边,那么最优匹配不存在(即完备匹配不存在)

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<queue>
     4 #define _Clr(x, y) memset(x, y, sizeof(x))
     5 #define INF 0x3f3f3f3f
     6 #define N 1005
     7 using namespace std;
     8 
     9 int mat[N][N], match[N];
    10 int lx[N], ly[N];
    11 int slack[N];
    12 bool used_x[N], used_y[N];
    13 int n, m;
    14 
    15 bool dfs(int x)
    16 {
    17     used_x[x] = true;
    18     for(int i=1; i<=n; i++)
    19     {
    20         if(used_y[i]) continue;
    21         int t = lx[x] + ly[i] - mat[x][i];
    22         if(t==0)
    23         {
    24             used_y[i] = true;
    25             if(match[i]==-1 || dfs(match[i]))
    26             {
    27                 match[i] = x;
    28                 return true;
    29             }
    30         }
    31         else slack[i] = min(slack[i], t);
    32     }
    33     return false;
    34 }
    35 
    36 int KM()
    37 {
    38     _Clr(match, -1);
    39     _Clr(ly, 0);
    40     for(int i=1, j; i<=n; i++)
    41         for(j=1, lx[i]=-INF; j<=n; j++)
    42             lx[i] = max(lx[i], mat[i][j]);
    43     for(int x=1; x<=n; x++)
    44     {
    45         _Clr(slack, INF);
    46         while(1)
    47         {
    48             _Clr(used_x, 0);
    49             _Clr(used_y, 0);
    50             if(dfs(x)) break;
    51             int d=INF;
    52             for(int i=1; i<=n; i++)
    53                 if(!used_y[i] && d>slack[i])
    54                     d = slack[i];
    55             for(int i=1; i<=n; i++)
    56                 if(used_x[i])
    57                     lx[i] -= d;
    58             for(int i=1; i<=n; i++)
    59                 if(used_y[i])
    60                     ly[i] += d;
    61                 else slack[i] -= d;
    62         }
    63     }
    64     int ans=0;
    65     for(int i=1; i<=n; i++)
    66     {
    67         if(match[i]==-1 || mat[match[i]][i]==-INF) return -1;
    68         ans += mat[match[i]][i];
    69     }
    70     return -ans;
    71 }
    72 int main()
    73 {
    74     int m, a, b, c;
    75     while(~scanf("%d%d", &n, &m))
    76     {
    77         for(int i=1; i<=n; i++)
    78         for(int j=1; j<=n; j++)
    79             mat[i][j]=-INF;
    80         while(m--)
    81         {
    82             scanf("%d%d%d", &a, &b, &c);
    83             mat[a][b] = max(mat[a][b], -c);
    84         }
    85         printf("%d
    ", KM());
    86     }
    87     return 0;
    88 }

    例如:HDU 3435

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define _Clr(x, y) memset(x, y, sizeof(x))
     5 #define INF 0x3f3f3f3f
     6 #define N 1010
     7 using namespace std;
     8 
     9 int mat[N][N], match[N];
    10 int lx[N], ly[N];
    11 int slack[N], n;
    12 bool used_x[N], used_y[N];
    13 
    14 bool dfs(int x)
    15 {
    16     used_x[x] = true;
    17     for(int i=1; i<=n; i++)
    18     {
    19         if(used_y[i]) continue;
    20         int t=lx[x]+ly[i]-mat[x][i];
    21         if(t==0)
    22         {
    23             used_y[i] = true;
    24             if(match[i]==-1 || dfs(match[i]))
    25             {
    26                 match[i] = x;
    27                 return true;
    28             }
    29         }
    30         else slack[i] = min(slack[i], t);
    31     }
    32     return false;
    33 }
    34 
    35 int KM()
    36 {
    37     _Clr(match, -1);
    38     _Clr(ly, 0);
    39     for(int i=1, j=1; i<=n; i++)
    40     for(j=1, lx[i]=-INF; j<=n; j++)
    41         lx[i] = max(lx[i], mat[i][j]);
    42     for(int x=1; x<=n; x++)
    43     {
    44         _Clr(slack, INF);
    45         while(1)
    46         {
    47             _Clr(used_x, 0);
    48             _Clr(used_y, 0);
    49             if(dfs(x)) break;
    50             int d=INF;
    51             for(int i=1; i<=n; i++)
    52                 if(!used_y[i] && slack[i]<d)
    53                     d = slack[i];
    54             for(int i=1; i<=n; i++)
    55                 if(used_x[i]) lx[i] -= d;
    56             for(int i=1; i<=n; i++)
    57                 if(used_y[i]) ly[i] += d;
    58                 else slack[i] -= d;
    59         }
    60     }
    61     int ans=0;
    62     for(int i=1; i<=n; i++)
    63     {
    64         if(match[i]==-1 || mat[match[i]][i]==-INF) return 0;
    65         ans += mat[match[i]][i];
    66     }
    67     return ans;
    68 }
    69 
    70 int main()
    71 {
    72     int m, T, a, b, c;
    73     int lop=1;
    74     scanf("%d", &T);
    75     while(T--)
    76     {
    77         scanf("%d%d", &n, &m);
    78         for(int i=1; i<=n; i++)
    79         for(int j=1; j<=n; j++)
    80             mat[i][j] = -INF;
    81         while(m--)
    82         {
    83             scanf("%d%d%d", &a, &b, &c);
    84             mat[a][b] = mat[b][a] = max(mat[a][b], -c);
    85         }
    86         printf("Case %d: ", lop++);
    87         int ans = KM();
    88         if(ans==0) puts("NO");
    89         else printf("%d
    ", -ans);
    90     }
    91 }
    View Code
  • 相关阅读:
    asp中动态include的方法
    asp存储过程使用大全
    用vb6写asp组件的简单例子
    asp中遍历一些对象(request,session,Application)
    查看ASP Session 变量的小工具
    层不能跨框架(包括TEXTAREA)显示的解决办法
    保存远程图片到本地 同时取得第一张图片并创建缩略图
    使用.Net开发asp组件
    使用ASP在IIS创建WEB站点
    解析notes自带的rtf javaapplet编辑器
  • 原文地址:https://www.cnblogs.com/khan724/p/4379477.html
Copyright © 2020-2023  润新知