HDU 3488 Tour

有向环最小权值覆盖问题

http://blog.csdn.net/u013480600/article/details/39159407

#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;

//设置节点数量
const int maxn=450+10;

const int INF=0x7FFFFFFF;
struct Edge
{
    int from,to,cap,flow,cost;
};
int n,m,len,s,t;
vector<Edge> edges;
vector<int> G[maxn];
int inq[maxn];
int d[maxn];
int p[maxn];
int a[maxn];

void init()
{
    for(int i=0; i<maxn; i++) G[i].clear();
    edges.clear();
}

void Addedge(int from,int to,int cap,int cost)
{
    edges.push_back((Edge)
    {
        from,to,cap,0,cost
    });
    edges.push_back((Edge)
    {
        to,from,0,0,-cost
    });
    len=edges.size();
    G[from].push_back(len-2);
    G[to].push_back(len-1);
}

bool BellmanFord(int s,int t,int &flow,int &cost)
{

    for(int i=0; i<maxn; i++) d[i]=INF;

    memset(inq,0,sizeof(inq));
    memset(p,-1,sizeof(p));

    d[s]=0;
    inq[s]=1;
    p[s]=0;
    a[s]=INF;

    queue<int>Q;
    Q.push(s);
    while(!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        inq[u]=0;
        for(int i=0; i<G[u].size(); i++)
        {
            Edge& e=edges[G[u][i]];
            if(e.cap>e.flow&&d[e.to]>d[u]+e.cost)
            {
                d[e.to]=d[u]+e.cost;
                p[e.to]=G[u][i];
                a[e.to]=min(a[u],e.cap-e.flow);
                if(!inq[e.to])
                {
                    Q.push(e.to);
                    inq[e.to]=1;
                }
            }
        }
    }
    if(d[t]==INF) return false;
    flow+=a[t];
    cost+=d[t]*a[t];
    int u=t;
    while(u!=s)
    {
        edges[p[u]].flow+=a[t];
        edges[p[u]^1].flow-=a[t];
        u=edges[p[u]].from;
    }
    return true;
}

void Mincost (int s,int t)
{
    int flow=0,cost=0;
    while(BellmanFord(s,t,flow,cost));
    printf("%d\n",cost);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        init();
        s=0; t=2*n+1;
        for(int i=1; i<=n; i++) Addedge(s,i,1,0);
        for(int i=1; i<=n; i++) Addedge(i+n,t,1,0);
        for(int i=1; i<=m; i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            Addedge(u,v+n,1,w);
        }
        Mincost(s,t);
    }
    return 0;
}
时间: 2024-08-04 00:27:34

HDU 3488 Tour的相关文章

Hdu 3488 Tour (KM 有向环覆盖)

题目链接: Hdu 3488 Tour 题目描述: 有n个节点,m条有权单向路,要求用一个或者多个环覆盖所有的节点.每个节点只能出现在一个环中,每个环中至少有两个节点.问最小边权花费为多少? 解题思路: 因为每个节点就出现一个,那么每个节点出度和入度都为1咯.我们可以对每个节点u拆点为u,u',分别放在集合X,Y.然后对两个集合进行完备匹配.完备匹配成功以后,每个节点就会有只有一个出度,一个入度的. 用KM求最小匹配的话,先初始化maps为-INF,然后把各边权值存为负,求出最大值取反即可. 1

HDU 3488 Tour【多个环的并】

大意:告诉你一些国家和一些单项路,每条路连接两个国家,告诉你之间的距离,现在要使每个国家都在一个环中 求最小距离 分析:这是做过的第二个多个环的并的问题 每个点的入读和出度都为1 把n个点拆点 由于二分图最优匹配的性质可知每个点都会出现在匹配中 相当于每个点出现一次 左边为出度点  有边为入读点 值得注意的是两个国家可能会有多条路 要选取最短的 ----想起东北赛死在这上边了   ----全都是泪啊 代码: 1 #include <iostream> 2 #include <cstdio

HDU 3488 Tour (最大权完美匹配)【KM算法】

<题目链接> 题目大意:给出n个点m条单向边边以及经过每条边的费用,让你求出走过一个哈密顿环(除起点外,每个点只能走一次)的最小费用.题目保证至少存在一个环满足条件. 解题分析: 因为要求包含所有点一次的环,我们不难发现,这个环中的每个点的出度和入度均为1,所以我们不妨将每个点进行拆点,将所有点的出度和入度分为两部分.因为该环需要包括所有的点,并且题目需要求该环的最小权值,相当于该带权二分图的每个点都需要被覆盖到,由于本题就转化为求该二分图的最优完美匹配问题.二分图的最优匹配问题求解,我们会想

Tour HDU - 3488

Tour HDU - 3488 可以用费用流做 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int inf = 0x3f3f3f3f; 4 const int maxv = 410; 5 const int maxe = maxv * maxv; 6 7 struct Edge{ 8 int u, v, cap, flow, cost; 9 int nxt; 10 Edge(int u = 0, int v = 0, in

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

HDU 1853Cyclic Tour(网络流之最小费用流)

题目地址:HDU1853 费用流果然好神奇..还可以用来判断环...如果每个点都是环的一部分而且每个点只能用到一次的话,那每个点的初度入度都是1,这就可以利用网络流来解决,只要拆点令其流量为1,就限制了每个点只能用一次,每次左边的连到右边的,就相当于左边点的一次初度和右边的点的一次入度,很容易想象出来.最后只要判断总流量是否为n即可,因为如果总流量为n的话,说明每个点都出了一次度,每个点都入了一次度,而且由于拆点的流量限制,充分说明了每个点的初度入度都是1.进而说明了每个点都在环里.然后输出最后

hdu1853/ hdu 3488 有向图,取k个圈覆盖所有点一次//费用流

哎╮(╯▽╰)╭,这是费用流基础题型,拆点,建二分图,跑最小费用最大流即可.若最大流为n,则说明是最大匹配为n,所有点都参与,每个点的入度和出度又是1,所以就是环. 弱菜还需努力! #include<cstdio> #include<iostream> #include<queue> #include<cstring> using namespace std; const int inf=0x3f3f3f3f; int nume=0;int e[50000]

hdoj 3488 Tour 【经典最小费用最大流】

题目:hdoj 3488 Tour 题意:给出n个点m条边,然后让你求每个点只能在一个环中(哈密顿环),且所有点只走一次的最小费用. 分析:直接画图的话可能没有思路,但是把它化成一个二分图的话肯定瞬间思路来了,每个点只走一次,很好建图 建图方案: 每个点拆成两个i 和 ii 然后s连接所有 i ,容量1 ,费用0 ii 连接所有 t ,容量 1 ,费用0 所有右边的点 xi 连接 yii ,费用为权值,容量0 AC代码: #include <cstdlib> #include <ccty

Tour HDU - 3488(最大权值匹配)

Tour 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 o