poj 2135 Farm Tour 【无向图最小费用最大流】

题目:poj 2135 Farm Tour 


题意:给出一个无向图,问从 1 点到 n 点然后又回到一点总共的最短路。


分析:这个题目不读仔细的话可能会当做最短路来做,最短路求出来的不一定是最优的,他是两条分别最短,但不一定是和最短。

我们可以用费用流来很轻易的解决,建边容量为1,费用为边权,然后源点s连 1 ,费用0 ,容量 2 ,n点连接汇点,容量2,费用0,,就可以了。

注意这个题目是无向图,所以要建双向边。


AC代码:

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <cstring>
using namespace std;
const int N = 1050;
const int inf = 0x3f3f3f3f;
#define Del(a,b) memset(a,b,sizeof(a))
struct Node
{
    int from,to,cap,flow,cost;
};
vector<int> v[N];
vector<Node> e;
void add_Node(int from,int to,int cap,int cost)
{
    e.push_back((Node){from,to,cap,0,cost});
    e.push_back((Node){to,from,0,0,-cost});
    int len = e.size()-1;
    v[to].push_back(len);
    v[from].push_back(len-1);
}
int vis[N],dis[N];
int father[N],pos[N];
bool BellManford(int s,int t,int& flow,int& cost)
{
    Del(dis,inf);
    Del(vis,0);
    queue<int> q;
    q.push(s);
    vis[s]=1;
    father[s]=-1;
    dis[s] = 0;
    pos[s] = inf;
    while(!q.empty())
    {
        int f = q.front();
        q.pop();
        vis[f] = 0;
        for(int i=0; i<v[f].size(); i++)
        {
            Node& tmp = e[v[f][i]];
            if(tmp.cap>tmp.flow && dis[tmp.to] > dis[f] + tmp.cost)
            {
                dis[tmp.to] = dis[f] + tmp.cost;
                father[tmp.to] = v[f][i];
                pos[tmp.to] = min(pos[f],tmp.cap - tmp.flow);
                if(vis[tmp.to] == 0)
                {
                    vis[tmp.to]=1;
                    q.push(tmp.to);
                }
            }
        }
    }
    if(dis[t] == inf)
        return false;
    flow += pos[t];
    cost += dis[t]*pos[t];
    for(int u = t; u!=s ; u = e[father[u]].from)
    {
        e[father[u]].flow += pos[t];
        e[father[u]^1].flow -= pos[t];
    }
    return true;
}
int Mincost(int s,int t)
{
    int flow = 0, cost = 0;
    while(BellManford(s,t,flow,cost)){}
    return cost;
}
void Clear(int x)
{
    for(int i=0; i<=x; i++)
        v[i].clear();
    e.clear();
}

int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0;i<m;i++)
        {
            int x,y,z;
            scanf("%d%d%d",&x,&y,&z);
            add_Node(x,y,1,z);
            add_Node(y,x,1,z);
        }
        int s = 0 ,t = n+1;
        add_Node(s,1,2,0);
        add_Node(n,t,2,0);
        int ans = Mincost(s,t);
        printf("%d\n",ans);
        Clear(n+1);
    }
    return 0;
}


你可能感兴趣的:(Algorithm,namespace,最短路算法,二分图染色)