POJ 2135 Farm Tour and HDU 1853 Cyclic Tour(费用流初运用)

来源:互联网 发布:和网络有关的英文单词 编辑:程序博客网 时间:2024/06/05 23:01

Farm Tour(传送门)

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 15477 Accepted: 5966

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

Source

USACO 2003 February Green

题意

给你N个顶点,M条边,求解从1N然后从N1的最短路,每一条只允许访问一次.

解题思路

0构造一条边到1,它的容量为2,然后构造一条NN+1的边,容量也为2,接着费用流模版走一边,求解0N+1的最小费用流即可.

代码

#include <cstdio>#include <cstring>#include <cstdlib>#include <queue>#include <iostream>#include <algorithm>#include <functional>using namespace std;typedef pair<int,int > PII;const int MAXN = 4e4 + 5;const int INF = 0x3f3f3f3f;struct Edge{    int u, v, cap, flow, cost, nxt;}E[MAXN << 1];int Head[MAXN], tot;int pre[MAXN], dis[MAXN];bool vis[MAXN];void edge_init(){    tot = 0;    memset(Head, -1, sizeof(Head));}void add_edge(int u, int v, int cap, int cost){    E[tot].u = u;    E[tot].v = v;    E[tot].cap = cap;    E[tot].flow = 0;    E[tot].cost = cost;    E[tot].nxt = Head[u];    Head[u] = tot ++;    E[tot].u = v;    E[tot].v = u;    E[tot].cap = 0;    E[tot].flow = 0;    E[tot].cost = -cost;    E[tot].nxt = Head[v];    Head[v] = tot ++;}bool spfa(int start, int end){    queue<int>q;    memset(vis, false, sizeof(vis));    memset(pre, -1, sizeof(pre));    memset(dis, 0x3f, sizeof(dis));    dis[start] = 0;    vis[start] = true;    q.push(start);    while(!q.empty()){        int u = q.front();        q.pop();        vis[u] = false;        for(int i = Head[u]; ~i;i = E[i].nxt){            int v = E[i].v;            if(E[i].cap - E[i].flow && dis[v] > dis[u] + E[i].cost){                dis[v] = dis[u] + E[i].cost;                pre[v] = i;                if(!vis[v]){                    vis[v] = true;                    q.push(v);                }            }        }    }    if(pre[end] == -1) return false;    return true;}PII min_flow(int s,int t){    int flow = 0;    int cost = 0;    while(spfa(s, t)){        int Min = INF;        for(int i = pre[t];~i;i = pre[E[i].u]){            if(Min > E[i].cap - E[i].flow){                Min = E[i].cap - E[i].flow;            }        }        for(int i = pre[t]; ~i;i = pre[E[i].u]){            E[i].flow += Min;            E[i ^ 1].flow -= Min;            cost += E[i].cost * Min;        }        flow += Min;    }    return make_pair(flow, cost);}int N, M;int main(){    while(~scanf("%d%d",&N, &M)){        int a, b, c;        edge_init();        for(int i = 0;i < M;i ++){            scanf("%d%d%d", &a, &b, &c);            add_edge(a, b, 1, c);            add_edge(b, a, 1, c);        }        add_edge(0, 1, 2, 0);        add_edge(N, N + 1, 2, 0);        PII aa = min_flow(0, N + 1);        printf("%d\n", aa.second);    }    return 0;}

Cyclic Tour(传送门)

Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/65535 K (Java/Others)
Total Submission(s): 2366 Accepted Submission(s): 1211

Problem Description

There are N cities in our country, and M one-way roads connecting them. Now Little Tom wants to make several cyclic tours, which satisfy that, each cycle contain at least two cities, and each city belongs to one cycle exactly. Tom wants the total length of all the tours minimum, but he is too lazy to calculate. Can you help him?

Input

There are several test cases in the input. You should process to the end of file (EOF).
The first line of each test case contains two integers N(N100) and M, indicating the number of cities and the number of roads. The M lines followed, each of them contains three numbers A, B, and C, indicating that there is a road from city A to city B, whose length is C.(1A,BN,AB,1C1000).

Output

Output one number for each test case, indicating the minimum length of all the tours. If there are no such tours, output 1.

Sample Input

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
6 5
1 2 1
2 3 1
3 4 1
4 5 1
5 6 1

Sample Output

42
-1

Hint

In the first sample, there are two cycles, (1->2->3->1) and (6->5->4->6) whose length is 20+22=42.

Author

RoBa@TJU

Source

HDU 2007 Programming Contest - Final

Recommend

lcy

题意

N个点,M条边,让这n个点组成多个环,使得每个点只能在一个环中 每个环最少2个点,求满足上面条件时,所有环的路径权值的和最小是多少

解题思想

将每一个点进行拆点处理,然后创建超级源点0到每一个点,容量为1,费用为0,容量为1的原因是让他们的入度为1,并且只能通过一遍,然后创建超级汇点2N+1到每一个点,容量为1,费用为0, 容量为1的原因是为了让他们的出度为1也是只能访问一遍,当我们的路径构成一个环或者多个环时,他们的入度肯定等于出度,所以最终的流量值必须为N,否则无解,然后如果uv有边,则建立一条容量为1,费用为这条边的花费c,容量为1是为了让每一条边有且只能访问一遍,然后求解一遍费用流即可,这道题目的难点基本就是用出度和入度来控制一个点的访问次数以及构建环图的基础。

代码

#include <cstdio>#include <queue>#include <cstring>#include <algorithm>#include <functional>using namespace std;typedef pair<int, int > PII;const int MAXN = 4e2 + 5;const int INF = 0x3f3f3f3f;struct Edge{    int u, v, cap, flow, nxt, cost;}E[MAXN * MAXN];int Head[MAXN], tot;int pre[MAXN], dis[MAXN];bool vis[MAXN];void edge_init(){    tot = 0;    memset(Head, -1, sizeof(Head));}void add_edge(int u, int v, int cap, int cost){    E[tot].u = u;    E[tot].v = v;    E[tot].cap = cap;    E[tot].flow = 0;    E[tot].cost = cost;    E[tot].nxt = Head[u];    Head[u] = tot ++;    E[tot].u = v;    E[tot].v = u;    E[tot].cap = 0;    E[tot].flow = 0;    E[tot].cost = -cost;    E[tot].nxt = Head[v];    Head[v] = tot ++;}bool spfa(int s, int t, int sz){    memset(dis, 0x3f, sizeof(dis));    memset(vis, false, sizeof(vis));    memset(pre, -1, sizeof(pre));    queue<int>q;    vis[s] = true;    dis[s] = 0;    q.push(s);    while(!q.empty()){        int u = q.front();        q.pop();        vis[u] = false;        for(int i = Head[u]; ~i;i = E[i].nxt){            int v = E[i].v;            if(E[i].cap - E[i].flow && dis[v] > dis[u] + E[i].cost){                dis[v] = dis[u] + E[i].cost;                pre[v] = i;                if(!vis[v]){                    vis[v] = true;                    q.push(v);                }            }        }    }    if(pre[t] == -1) return false;    return true;}PII min_flow(int s, int t, int N){    int flow = 0;    int cost = 0;    while(spfa(s, t, N)){        int Min = INF;        for(int i = pre[t]; ~i ;i = pre[E[i].u]){            if(Min > E[i].cap - E[i].flow){                Min = E[i].cap - E[i].flow;            }        }        for(int i = pre[t]; ~i;i = pre[E[i].u]){            E[i].flow += Min;            E[i ^ 1].flow -= Min;            cost += E[i].cost * Min;        }        flow += Min;    }    return make_pair(flow, cost);}int N, M;int main(){    while(~scanf("%d%d", &N, &M)){        int a, b, c;        edge_init();        for(int i = 1;i <= N;i ++){            add_edge(0, i, 1, 0);        }        for(int i = 1;i <= N;i ++){            add_edge(i + N, 2 * N + 1, 1, 0);        }        for(int i = 0;i < M;i ++){            scanf("%d%d%d", &a, &b, &c);            add_edge(a, b + N, 1, c);        }        PII aa = min_flow(0, 2 * N + 1, 2 * N + 2);        if(aa.first != N) aa.second = -1;        printf("%d\n", aa.second);    }    return 0;}
1 0