1. 程式人生 > >【二分圖匹配入門專題1】M - Cyclic Tour hdu1853【km算法--判斷自重邊】

【二分圖匹配入門專題1】M - Cyclic Tour hdu1853【km算法--判斷自重邊】

初始化 case test case 思路 contain first rst ant eve

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

【二分圖匹配入門專題1】M - Cyclic Tour hdu1853【km算法--判斷自重邊】