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
个顶点,
解题思路
从
0
构造一条边到
代码
#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
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(N≤100)
and
M
, indicating the number of cities and the number of roads. The
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
个点,
解题思想
将每一个点进行拆点处理,然后创建超级源点
0
到每一个点,容量为
代码
#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;
}