hdu 3488(KM算法||最小费用最大流)

Tour

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 2925    Accepted Submission(s): 1407

Problem Description

In
the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M
(M <= 30000) one-way roads connecting them. You are lucky enough to
have a chance to have a tour in the kingdom. The route should be
designed as: The route should contain one or more loops. (A loop is a
route like: A->B->……->P->A.)
Every city should be just in one route.
A
loop should have at least two cities. In one route, each city should be
visited just once. (The only exception is that the first and the last
city should be the same and this city is visited twice.)
The total distance the N roads you have chosen should be minimized.

Input

An integer T in the first line indicates the number of the test cases.
In
each test case, the first line contains two integers N and M,
indicating the number of the cities and the one-way roads. Then M lines
followed, each line has three integers U, V and W (0 < W <=
10000), indicating that there is a road from U to V, with the distance
of W.
It is guaranteed that at least one valid arrangement of the tour is existed.
A blank line is followed after each test case.

Output

For each test case, output a line with exactly one integer, which is the minimum total distance.

Sample Input

1
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

Sample Output

42

题意:和hdu 1853题意和解法几乎一样,但是这题我看英文硬是没看懂。。。题意就是n个城市,每个城市都必须在一个环里面并且也只能出现在一个环里面?问最小的花费是多少?

题解:解法一:最小费用最大流:要去重 不然TLE。每个点只能出现一次,那么一个点容量限制为1,然后拆点跑最小费用最大流即可.

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int INF = 999999999;
const int N = 405;
const int M = 200005;
struct Edge{
    int u,v,cap,cost,next;
}edge[M];
int head[N],tot,low[N],pre[N];
int total ;
bool vis[N];
int flag[N][N];
void addEdge(int u,int v,int cap,int cost,int &k){
    edge[k].u=u,edge[k].v=v,edge[k].cap = cap,edge[k].cost = cost,edge[k].next = head[u],head[u] = k++;
    edge[k].u=v,edge[k].v=u,edge[k].cap = 0,edge[k].cost = -cost,edge[k].next = head[v],head[v] = k++;
}
void init(){
    memset(head,-1,sizeof(head));
    tot = 0;
}
bool spfa(int s,int t,int n){
    memset(vis,false,sizeof(vis));
    for(int i=0;i<=n;i++){
        low[i] = (i==s)?0:INF;
        pre[i] = -1;
    }
    queue<int> q;
    q.push(s);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int k=head[u];k!=-1;k=edge[k].next){
            int v = edge[k].v;
            if(edge[k].cap>0&&low[v]>low[u]+edge[k].cost){
                low[v] = low[u] + edge[k].cost;
                pre[v] = k; ///v为终点对应的边
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    if(pre[t]==-1) return false;
    return true;
}
int MCMF(int s,int t,int n){
    int mincost = 0,minflow,flow=0;
     while(spfa(s,t,n))
    {
        minflow=INF+1;
        for(int i=pre[t];i!=-1;i=pre[edge[i].u])
            minflow=min(minflow,edge[i].cap);
        flow+=minflow;
        for(int i=pre[t];i!=-1;i=pre[edge[i].u])
        {
            edge[i].cap-=minflow;
            edge[i^1].cap+=minflow;
        }
        mincost+=low[t]*minflow;
    }
    total=flow;
    return mincost;
}
int n,m;
int main(){
     int tcase;
     scanf("%d",&tcase);
     while(tcase--){
        init();
        scanf("%d%d",&n,&m);
        int src = 0,des = 2*n+1;
        for(int i=1;i<=n;i++){
            addEdge(src,i,1,0,tot);
            addEdge(i+n,des,1,0,tot);
        }
        memset(flag,-1,sizeof(flag));
        for(int i=1;i<=m;i++){  ///去重
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            if(flag[u][v]==-1||w<flag[u][v]){
                flag[u][v] = w;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(flag[i][j]!=-1){
                    addEdge(i,j+n,1,flag[i][j],tot);
                }
            }
        }
        int mincost = MCMF(src,des,2*n+2);
        if(total!=n) printf("-1\n");
        else printf("%d\n",mincost);
     }
}

题解二:KM算法,也是将一个点看成两个点,算最优匹配即可.

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int INF = 999999999;
const int N = 405;
int graph[N][N];
int lx[N],ly[N];
int linker[N];
bool x[N],y[N];
int n,m;
void init(){
    memset(lx,0,sizeof(lx));
    memset(ly,0,sizeof(ly));
    memset(linker,-1,sizeof(linker));
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(lx[i]<graph[i][j]) lx[i] = graph[i][j];
        }
    }
}
bool dfs(int u){
    x[u] = true;
    for(int i=1;i<=n;i++){
        if(!y[i]&&graph[u][i]==lx[u]+ly[i]){
            y[i] = true;
            if(linker[i]==-1||dfs(linker[i])){
                linker[i] = u;
                return true;
            }
        }
    }
    return false;
}
int KM(){
    int sum = 0;
    init();
    for(int i=1;i<=n;i++){
        while(1){
            memset(x,false,sizeof(x));
            memset(y,false,sizeof(y));
            if(dfs(i)) break;
            int d = INF;
            for(int j=1;j<=n;j++){
                if(x[j]){
                    for(int k=1;k<=n;k++){
                        if(!y[k]) d = min(d,lx[j]+ly[k]-graph[j][k]);
                    }
                }
            }
            if(d==INF) break;
            for(int j=1;j<=n;j++){
                if(x[j]) lx[j]-=d;
                if(y[j]) ly[j]+=d;
            }
        }
    }
    for(int i=1;i<=n;i++){
        sum+=graph[linker[i]][i];
    }
    return sum;
}
int main()
{
    int tcase;
    scanf("%d",&tcase);
    while(tcase--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                graph[i][j] = -INF;
            }
        }
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            graph[u][v] = max(graph[u][v],-w);
        }
        int ans = KM();
        printf("%d\n",-ans);
    }
    return 0;
}
时间: 2024-12-15 01:35:51

hdu 3488(KM算法||最小费用最大流)的相关文章

hdu 4862 KM算法 最小K路径覆盖的模型

http://acm.hdu.edu.cn/showproblem.php?pid=4862 选t<=k次,t条路要经过所有的点一次并且仅仅一次, 建图是问题: 我自己最初就把n*m 个点分别放入X集合以及Y集合,再求最优匹配,然后连样例都过不了,而且其实当时解释不了什么情况下不能得到结果,因为k此这个条件相当于没用上... 建图方法: 1.X集合和Y集合都放入n*m+k个点,X中前n*m个点和Y中前n*m个点之间,如果格子里的值相等,权就是(收益-耗费),不等就是(-耗费),因为要的是最大收益

hdu 1533 Going Home 最小费用最大流

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1533 On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically, to an adjacent point. For each little man, you need

hdu 1853 Cyclic Tour 最小费用最大流

题意:一个有向图,现在问将图中的每一个点都划分到一个环中的最少代价(边权和). 思路:拆点,建二分图,跑最小费用最大流即可.若最大流为n,则说明是最大匹配为n,所有点都参与,每个点的入度和出度又是1,所以就是环. /********************************************************* file name: hdu1853.cpp author : kereo create time: 2015年02月16日 星期一 17时38分51秒 *******

hdu 1533 Going Home 最小费用最大流 入门题

Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3125    Accepted Submission(s): 1590 Problem Description On a grid map there are n little men and n houses. In each unit time, every

HDU 1533--Going Home【最小费用最大流 &amp;&amp; 模板】

Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3452    Accepted Submission(s): 1771 Problem Description On a grid map there are n little men and n houses. In each unit time, every

HDU ACM 4494 Teamwork 最小费用最大流

题意:n个工作地,m种工人,工作地0是仓库,其他的都需要修缮,每个地点需要多个工种的工人若干,不同工种不能相互取代.每个工作地有一个开工时间,凑齐所有工人后准时开工,修缮也需要一定时间.一个工人可以在一个地方工作完后再到其他地方,两地直接的距离是欧几里得距离,可以算作时间.最少需要多少工人. 分析:只用费用流.每种工人不能相互替换,没有任何关系.因此对每个工种进行建图求解最小费用累加即可得到最终结果. 超级源点cs是仓库,超级汇点为ct. 一个地点拆成三个点,i.i'.i".k表示工种,对每个点

hdoj 3488 Tour 【最小费用最大流】【KM算法】

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 2299    Accepted Submission(s): 1151 Problem Description In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 3000

HDU 1853--Cyclic Tour【最小费用最大流 &amp;&amp; 有向环最小权值覆盖 】

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

POJ 2195 &amp; HDU 1533 Going Home(最小费用最大流)

题目链接: POJ:http://poj.org/problem?id=2195 HDU:http://acm.hdu.edu.cn/showproblem.php?pid=1533 Description On a grid map there are n little men and n houses. In each unit time, every little man can move one unit step, either horizontally, or vertically,