首页 > 其他 > 详细

hdu 3488 Tour

时间:2017-12-21 23:35:52      阅读:232      评论:0      收藏:0      [点我收藏+]

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

原文:http://www.cnblogs.com/TheRoadToTheGold/p/8082722.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!