hdu1853 Cyclic Tour (二分图匹配KM)

Cyclic Tour

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others)
Total Submission(s): 1688    Accepted Submission(s): 859

Problem Description

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?

Input

There 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).

Output

Output 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.

题意:给一个有向有权图,选一些边使得每个点都在且只在一个环之中,且要求权值走过的边的权值最小

思路:

    可以发现,每个点的入度和出度都是1。

如果每个点都拆成入点和出点,对于点u,可以拆成u和u’, u是入点,u’是出点。

若有边(u, v),则u’ -> v连边

这样整个图转化为一个二分图。由于每个入点需要找一个出点连接,每个出点也要找一个入点连接,那么就是经典的二分图匹配问题。加上一个权值,就是二分图最优匹配问题。用KM或者最小费用流都可以解决。

这题卡了几天,因为KM模版都是每一个x点都和每一个y点连上了,而这条题目只是部分连了而已,不懂得处理

后来看题解处理方法只是最后统计答案的时候,如果g[linker[y]][y]==-INF的话就跳过

求最小匹配的处理就是把权值换成负的就可以了

第一次交wa了,因为没考虑到重边的情况,这些题要考虑判重自环呀

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <map>
#include <utility>
#include <queue>
#include <stack>
using namespace std;
const int INF=1e9;
const double eps=1e-6;
const int N = 210;

int nx,ny;
int g[N][N];
int linker[N],lx[N],ly[N];// x is outpoint, y is inpoint
int slack[N];
int visx[N],visy[N];

int n,m;

bool DFS(int x)
{
    visx[x]=true;
    for(int y=0;y<ny;y++)
    {
        if(visy[y]) continue;
        int tmp = lx[x]+ly[y]-g[x][y];
        if(tmp==0)
        {
            visy[y]=true;
            if(linker[y]==-1||DFS(linker[y]))
            {
                linker[y]=x;
                return true;
            }
        }
        else if(slack[y]>tmp)
            slack[y]=tmp;
    }
    return false;
}

int KM()
{
    memset(linker,-1,sizeof(linker));
    memset(ly,0,sizeof(ly));
    for(int i=0;i<nx;i++)
    {
        lx[i]=-INF;
        for(int j=0;j<ny;j++)
            if(g[i][j]>lx[i])
                lx[i]=g[i][j];
    }
    for(int x=0;x<nx;x++)
    {
        for(int i=0;i<ny;i++)
            slack[i]=INF;
        while(true)
        {
            memset(visx,false,sizeof(visx));
            memset(visy,false,sizeof(visy));
            if(DFS(x)) break;
            int d = INF;
            for(int i=0;i<ny;i++)
                if(!visy[i] && d>slack[i])
                    d=slack[i];
            for(int i=0;i<nx;i++)
                if(visx[i])
                    lx[i]-=d;
            for(int i=0;i<ny;i++)
            {
                if(visy[i]) ly[i]+=d;
                else slack[i]-=d;
            }
        }
    }
    int res = 0, cnt = 0;
    for(int i=0;i<ny;i++)
    {
        if(linker[i]==-1 || g[linker[i]][i]==-INF)
            continue;
        res += g[linker[i]][i];
        cnt++;
    }
    if(cnt!=nx) return -1;
    return -res;
}

void run()
{
//    memset(g,0,sizeof(g));
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
            g[i][j]=-INF;
    int u,v,c;
    while(m--)
    {
        scanf("%d%d",&u,&v);
        scanf("%d",&c);
        if(-c>g[u-1][v-1])
            g[u-1][v-1]=-c;
    }
    nx=ny=n;
    printf("%d\n",KM());
}

int main()
{
    #ifdef LOCAL
    freopen("case.txt","r",stdin);
    #endif // LOCAL
    while(scanf("%d%d",&n,&m)!=EOF)
        run();
    return 0;
}
时间: 2024-10-06 22:58:15

hdu1853 Cyclic Tour (二分图匹配KM)的相关文章

hdu1853 Cyclic Tour 完美匹配 验证模版

题意: 给出n个城市和m条路,每个城市只能经过一次,想要旅游所有的城市,求需要的最小花费(路径的长度). 对于我来说,这题就是验证模版.把输入数据全部改为负数,错误了返回1.最后乘以-1就行了. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 const int N=110, INF=0x3f3

训练指南 UVALive - 4043(二分图匹配 + KM算法)

layout: post title: 训练指南 UVALive - 4043(二分图匹配 + KM算法) author: "luowentaoaa" catalog: true mathjax: true tags: - 二分图匹配 - 图论 - 训练指南 Ants UVALive - 4043 题意 给你n个白点和n个黑点的平面坐标,要求用n条不相交的线连起来,每条线段连一个白点和黑点,每个点连一条线,也就是匹配.让你输出第i个白点所对应的黑点. 思路 二分图完美匹配问题.但是题目

费用流 hdu1853 Cyclic Tour

传送门:点击打开链接 题意:给n个点和M条有向边,要找出许多个环出来,每个环点至少有2个,所有的点都要被环覆盖1次,且只能为1次.问所有环的长度之和 这题也可以用KM来做,这里主要是练习费用流的建图 对于这题,建图也是非常的奇妙的 由于每个点的入度都是1,出度都是1 所以会想到把每个点拆分成2个点,用i和i+n来表示 然后将源点与所有的i连接起来,将汇点与所有的i+n连接起来,容量都是1 对于每一条边(u,v),添加边(u,v+n,1,cost),让第一层的点连接到第二层去 其实就是将点拆分成两

HDU-1853 Cyclic Tour

最小权值环覆盖问题:用几个环把所有点覆盖,求所选取的边最小的权值之和. 拆点思想+求最小转求最大+KM算法 #include <cstdlib> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <fstream> #include <iostream> #define rep(i, l, r) for(i

HDU 1853 Cyclic Tour(KM完美匹配)

HDU 1853 Cyclic Tour 题目链接 题意:一个有向图,边有权值,求把这个图分成几个环,每个点只能属于一个环,使得所有环的权值总和最小,求这个总和 思路:KM完美匹配,由于是环,所以每个点出度入度都是1,一个点拆成两个点,出点和入点,每个点只能用一次,这样就满足了二分图匹配,然后用KM完美匹配去就最小权值的匹配即可 代码: #include <cstdio> #include <cstring> #include <cmath> #include <

Cyclic Tour (hdu 1853 二分图最小权问题)

Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Total Submission(s): 1883    Accepted Submission(s): 941 Problem Description There are N cities in our country, and M one-way roads connecting them. Now L

hdu 1853 Cyclic Tour 最大权值匹配 全部点连成环的最小边权和

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Total Submission(s): 1904    Accepted Submission(s): 951 Problem Description There are N cities in our c

最大流增广路(KM算法) HDOJ 1853 Cyclic Tour

题目传送门 1 /* 2 KM: 相比HDOJ_1533,多了重边的处理,还有完美匹配的判定方法 3 */ 4 #include <cstdio> 5 #include <cmath> 6 #include <algorithm> 7 #include <cstring> 8 using namespace std; 9 10 const int MAXN = 1e2 + 10; 11 const int INF = 0x3f3f3f3f; 12 int x

hdu 1853 Cyclic Tour 最大权值匹配 所有点连成环的最小边权和

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853 Cyclic Tour Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/65535 K (Java/Others) Total Submission(s): 1904    Accepted Submission(s): 951 Problem Description There are N cities in our c