。。。

导航

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

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;
}

 

posted on 2017-08-14 15:37  大学僧  阅读(149)  评论(0编辑  收藏  举报