二分图匹配入门专题1M - Cyclic Tour hdu1853km算法--判断自重边

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二分图匹配入门专题1M - Cyclic Tour hdu1853km算法--判断自重边相关的知识,希望对你有一定的参考价值。

There are N cities in our country, and M one-way roads connecting them. Now Little Tom wants to make several cyclic tours, which satisfy that, each cycle contain at least two cities, and each city belongs to one cycle exactly. Tom wants the total length of all the tours minimum, but he is too lazy to calculate. Can you help him? 

InputThere are several test cases in the input. You should process to the end of file (EOF). 
The first line of each test case contains two integers N (N ≤ 100) and M, indicating the number of cities and the number of roads. The M lines followed, each of them contains three numbers A, B, and C, indicating that there is a road from city A to city B, whose length is C. (1 ≤ A,B ≤ N, A ≠ B, 1 ≤ C ≤ 1000). 
OutputOutput one number for each test case, indicating the minimum length of all the tours. If there are no such tours, output -1. 
Sample Input

6 9
1 2 5
2 3 5
3 1 10
3 4 12
4 1 8
4 6 11
5 4 7
5 6 9
6 5 4
6 5
1 2 1
2 3 1
3 4 1
4 5 1
5 6 1

Sample Output

42
-1


        
 

Hint

 In the first sample, there are two cycles, (1->2->3->1) and (6->5->4->6) whose length is 20 + 22 = 42. 
        
 

题意:输入n个顶点m条边,让这些顶点形成环,至少包括两个顶点.输出最小的完备匹配和,如果不存在,输出-1。

思路:把一个点一分为二,就形成了两个集合,求最小匹配,则将权值取负后求最大匹配,最后返回负值。如果图由多个有向环构成,则一定存在完备匹配,如果有权值最大的完备匹配存在,则一定是这个图的最优完备匹配的值,如果有任何一个匹配边是初始化的边权值,说明这个完备匹配不存在。

 

之前嫌弃题水,现在又写的头疼,今天一天到现在才出了3题,自己真的好菜啊,什么时候能像师父那样厉害就好了,感觉算法真的需要自己理解了才能够应对各种变形,就这道题就超时了

5遍,我怎么知道要判断重边啊~~~

#include<stdio.h>
#include<string.h>
#define N 210
#define INF 0x3f3f3f3f

int map[N][N];
int ans,d;
int w[N][N],lx[N],ly[N];
int linker[N],visx[N],visy[N];
int n,m,nx,ny;

int dfs(int x)
{
    int y,tmp;
    visx[x] = 1;
    for(y = 1; y <= ny; y ++)
    {
        if(!visy[y])
        {
            tmp = lx[x] + ly[y] - w[x][y];
            if(!tmp)
            {
                visy[y] = 1;
                if(linker[y]==-1||dfs(linker[y]))
                {
                    linker[y] = x;
                    return 1;
                }
            }
            else if( d > tmp)
                d = tmp;
        }
    }
    return 0;
}

int KM()
{
    int x,y,i,j,sum;
    memset(linker,-1,sizeof(linker));
    memset(ly,0,sizeof(ly));
    for(x = 1; x <= nx; x ++)
        for(y = 1,lx[x] = -INF; y <= ny; y ++)
            if(lx[x] < w[x][y])
                lx[x] = w[x][y];
                
    for(x = 1; x <= nx; x ++)
    {
        while(1)
        {
            d = INF;
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            if(dfs(x))
                break;
            for(i = 1; i <= nx; i ++)
                if(visx[i])
                    lx[i] -= d;
            for(i = 1; i <= ny; i ++)
                if(visy[i])
                    ly[i] += d;
        }
    }
    sum = 0;
    for(i = 1; i <= ny; i ++)
    {
        if(w[linker[i]][i] != -INF)
            sum += w[linker[i]][i];
        else
            return -1;
    }
    return -sum;
}

int main()
{
    int t1,t2,t3;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        nx = ny = n;
        for(int i = 1; i <= n; i ++)
            for(int j = 1; j <= n; j ++)
                w[i][j] = -INF;
        for(int i = 1; i <= m; i ++)
        {
            scanf("%d%d%d",&t1,&t2,&t3);
            if(-t3 > w[t1][t2])//重复输入取小值 
                w[t1][t2] = -t3;
        }
        ans = KM();
        printf("%d\n",ans);    
    }
    return 0;
}

 

以上是关于二分图匹配入门专题1M - Cyclic Tour hdu1853km算法--判断自重边的主要内容,如果未能解决你的问题,请参考以下文章

二分图匹配入门专题1K - Going Home hdu1533km匹配

二分图匹配入门专题1F - COURSES poj1469最大匹配--匈牙利算法模板题

二分图匹配入门专题1D - Matrix hdu2119最小顶点覆盖

二分图匹配入门专题1poj3686 km+思维建图

二分图匹配入门专题1L - Card Game hdu 3722km算法

二分图匹配入门专题1E - Air Raid hdu1151最小路径覆盖