POJ 2135 Farm Tour(费用流)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37943488/article/details/81434341

Farm Tour

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 19376   Accepted: 7527

Description

When FJ's friends visit him on the farm, he likes to show them around. His farm comprises N (1 <= N <= 1000) fields numbered 1..N, the first of which contains his house and the Nth of which contains the big barn. A total M (1 <= M <= 10000) paths that connect the fields in various ways. Each path connects two different fields and has a nonzero length smaller than 35,000. 

To show off his farm in the best way, he walks a tour that starts at his house, potentially travels through some fields, and ends at the barn. Later, he returns (potentially through some fields) back to his house again. 

He wants his tour to be as short as possible, however he doesn't want to walk on any given path more than once. Calculate the shortest tour possible. FJ is sure that some tour exists for any given farm.

Input

* Line 1: Two space-separated integers: N and M. 

* Lines 2..M+1: Three space-separated integers that define a path: The starting field, the end field, and the path's length. 

Output

A single line containing the length of the shortest tour. 

Sample Input

4 5
1 2 1
2 3 1
3 4 1
1 3 2
2 4 2

Sample Output

6

题目大意:FJ的农场包括N块地,1是他的家,N是大谷仓,中间有m条路,他要从家到大谷仓再返回家,每条路只能走一次,而且要走最短距离

之前遇到一个题是问有多少条最短路,而且只能走一边,用的是最大流,所以这道题也想到了最大流,但是有了最短距离的限制,容易想到用费用流,其实问题等同于是求从1到n有2条不重复的路径的总的距离(当然要尽量短),所以我们设置源点汇点,源点与第一个点连一条费用为0,容量为2的边,最后一个点向汇点连一条费用为0,容量为2的边,至于在无向图中的边,就连一条费用为权值,容量为1的边,跑费用流就可以了

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxm=2e4+7;
const int maxn=2e4+7;
const int inf=0x3f3f3f3f;
struct Node
{
    int to;
    int capa;
    int cost;
    int next;
}edge[maxm<<2];
int cnt;
int source,sink;
int head[maxn];
int dis[maxn];
bool vis[maxn];
int rec[maxn];
int pre[maxn];
void init()
{
    cnt=0;
    memset(head,-1,sizeof(head));
    return;
}
void add(int u,int v,int capa,int cost)
{
    edge[cnt].to=v;
    edge[cnt].capa=capa;
    edge[cnt].cost=cost;
    edge[cnt].next=head[u];
    head[u]=cnt++;
    edge[cnt].to=u;
    edge[cnt].capa=0;
    edge[cnt].cost=-cost;
    edge[cnt].next=head[v];
    head[v]=cnt++;
    return;
}
bool spfa()
{
    memset(dis,inf,sizeof(dis));
    memset(vis,false,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    memset(rec,-1,sizeof(rec));
    queue<int> que;
    dis[source]=0;
    vis[source]=true;
    que.push(source);
    while(!que.empty())
    {
        int node=que.front();
        que.pop();
        vis[node]=false;
        for(int i=head[node];~i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(edge[i].capa>0&&dis[v]>dis[node]+edge[i].cost)
            {
                dis[v]=dis[node]+edge[i].cost;
                rec[v]=i;
                pre[v]=node;
                if(!vis[v])
                {
                    vis[v]=true;
                    que.push(v);
                }
            }
        }
    }
    return dis[sink]!=inf;
}
int mcmf()
{
    int maxflow=0;
    int mincost=0;
    while(spfa())
    {
        int flow=inf;
        int node=sink;
        while(node!=source)
        {
            flow=min(flow,edge[rec[node]].capa);
            node=pre[node];
        }
        maxflow+=flow;
        node=sink;
        while(node!=source)
        {
            mincost+=flow*edge[rec[node]].cost;
            edge[rec[node]].capa-=flow;
            edge[rec[node]^1].capa+=flow;
            node=pre[node];
        }
    }
    return mincost;
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        init();
        for(int i=0;i<m;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,1,w);
            add(v,u,1,w);
        }
        source=0;
        sink=n+1;
		add(source,1,2,0);
        add(n,sink,2,0);
        printf("%d\n",mcmf());
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37943488/article/details/81434341
今日推荐