hdu 3488 Tour

Posted 日拱一卒 功不唐捐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 3488 Tour相关的知识,希望对你有一定的参考价值。

http://acm.hdu.edu.cn/showproblem.php?pid=3488

 

题意:

把有向图分成不相交的有向环. 且所有点都只被一个有向环覆盖.

有向环所有权值的总和最小是多少

 

点i拆为i和i+n

源点向i连流量为1,费用为0的边

i+n向汇点连流量为1,费用为0的边

存在有向边i-->j

i向j+n连流量为1,费用为边权的边

 

最大流保证了每个点用了且仅用一次

n个点,入度与出度均为1,保证了全是环

最小费用流保证比边权和最小

 

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>

using namespace std;

#define N 403
#define M 30401

const int inf=2e9;

int cost;

int tot;
int front[N],to[M<<1],nxt[M<<1],from[M<<1];
int val[M<<1],cap[M<<1];

int dis[N];
bool vis[N];

int src,decc;

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-0; c=getchar(); }
}

void add(int u,int v,int w,int f)
{
    to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; from[tot]=u; cap[tot]=w; val[tot]=f;
    to[++tot]=u; nxt[tot]=front[v]; front[v]=tot; from[tot]=v; cap[tot]=0; val[tot]=-f;
}

int augment(int now,int flow)
{
    vis[now]=true;
    if(now==decc) 
    {
        cost-=dis[src]*flow;
        return flow;
    }
    int delta;
    for(int i=front[now];i;i=nxt[i])
    {
        if(cap[i] && !vis[to[i]] && dis[to[i]]==dis[now]+val[i])
        {
            delta=augment(to[i],min(flow,cap[i]));
            if(delta)
            {
                cap[i]-=delta;
                cap[i^1]+=delta;
                return delta;
            }
        }
    }
    return 0;
}

bool retreat()
{
    if(vis[decc]) return true;
    int mi=inf;
    for(int i=2;i<=tot;++i)
        if(cap[i] && vis[from[i]] && !vis[to[i]]) 
            mi=min(mi,dis[from[i]]+val[i]-dis[to[i]]);
    if(mi==inf) return false;
    for(int i=src;i<=decc;++i)
        if(vis[i]) dis[i]-=mi;
    return true;
}

void zkw()
{
    cost=0;
    memset(dis,0,sizeof(dis));
    do
    {
        memset(vis,false,sizeof(vis));
        augment(src,inf);
    }while(retreat());
    cout<<cost<<\n;
}

int main()
{
    int T;
    read(T);
    int n,m;
    int u,v,w;
    while(T--)
    {
        tot=1;
        memset(front,0,sizeof(front));
        read(n);
        read(m);
        decc=n*2+1;
        for(int i=1;i<=n;++i) add(src,i,1,0);
        for(int i=1;i<=n;++i) add(i+n,decc,1,0);
        while(m--)
        {
            read(u);
            read(v);
            read(w);
            add(u,v+n,1,w);
        }
        zkw();
    }
}

 

Tour

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


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 3488 Tour的主要内容,如果未能解决你的问题,请参考以下文章

Tour HDU - 3488

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

hdu 3488 Tour

HDU3488 Tour —— 二分图最大权匹配 KM算法

HDU3488 Tour [有向环覆盖 费用流]

HDU 3488--Tour(KM or 费用流)