zoukankan      html  css  js  c++  java
  • 有向环覆盖问题

    转载自这里

      给你一个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
  • 相关阅读:
    Java RunTime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. ......
    UVA 1597 Searching the Web
    UVA 1596 Bug Hunt
    UVA 230 Borrowers
    UVA 221 Urban Elevations
    UVA 814 The Letter Carrier's Rounds
    UVA 207 PGA Tour Prize Money
    UVA 1592 Database
    UVA 540 Team Queue
    UVA 12096 The SetStack Computer
  • 原文地址:https://www.cnblogs.com/khan724/p/4379477.html
Copyright © 2011-2022 走看看