Cyclic Tour
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/65535 K (Java/Others)
Total Submission(s): 1269 Accepted Submission(s): 659
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 (N ≤ 100) 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. (1 ≤ A,B ≤ N, A ≠ B, 1 ≤ C ≤ 1000).
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 [email protected]
Source HDU 2007 Programming Contest - Final
Recommend lcy
这个题目应该讲其实是很不错的,但是我现在觉得建图真是一个大问题,因为实在想不到为什么这样建图,这样很是无奈的,唉,还是 做题目太少了
这就是建图的结果,然后我们用最大流和N比较,因为每个流之间都是1,所以如果是n,则证明是可以的,否则就不可以
#include <iostream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <queue>
using namespace std;
int sumFlow;
#define MAXN 505
#define MAXM 10005
#define INF 1000000000
struct Edge
{
int u, v, cap, cost;
int next;
}edge[MAXM<<2];
int NE;
int head[MAXN], dist[MAXN], pp[MAXN];
bool vis[MAXN];
char map[MAXN][MAXN];
void init()
{
NE = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int cap, int cost)
{
edge[NE].u = u; edge[NE].v = v; edge[NE].cap = cap; edge[NE].cost = cost;
edge[NE].next = head[u]; head[u] = NE++;
edge[NE].u = v; edge[NE].v = u; edge[NE].cap = 0; edge[NE].cost = -cost;
edge[NE].next = head[v]; head[v] = NE++;
}
bool SPFA(int s, int t, int n)
{
int i, u, v;
queue <int> qu;
memset(vis,false,sizeof(vis));
memset(pp,-1,sizeof(pp));
for(i = 0; i <= n; i++) dist[i] = INF;
vis[s] = true; dist[s] = 0;
qu.push(s);
while(!qu.empty())
{
u = qu.front(); qu.pop(); vis[u] = false;
for(i = head[u]; i != -1; i = edge[i].next)
{
v = edge[i].v;
if(edge[i].cap && dist[v] > dist[u] + edge[i].cost)
{
dist[v] = dist[u] + edge[i].cost;
pp[v] = i;
if(!vis[v])
{
qu.push(v);
vis[v] = true;
}
}
}
}
if(dist[t] == INF) return false;
return true;
}
int MCMF(int s, int t, int n) // minCostMaxFlow
{
int flow = 0; // 总流量
int i, minflow, mincost;
mincost = 0;
while(SPFA(s, t, n))
{
minflow = INF + 1;
for(i = pp[t]; i != -1; i = pp[edge[i].u])
if(edge[i].cap < minflow)
minflow = edge[i].cap;
flow += minflow;
for(i = pp[t]; i != -1; i = pp[edge[i].u])
{
edge[i].cap -= minflow;
edge[i^1].cap += minflow;
}
mincost += dist[t] * minflow;
}
sumFlow = flow; // 最大流
return mincost;
}
int main()
{
int n, m;
int u, v, c;
int i,j;
while (scanf("%d%d", &n, &m)!=EOF)
{
init();
int S = 0;
int T = 2*n+1;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&c);
addedge(u,v+n,1,c);
}
for(i=1;i<=n;i++)
{
addedge(0,i,1,0);
addedge(n+i,T,1,0);
}
int ans = MCMF(S, T, T+1);
if(sumFlow!=n)
printf("-1\n");
else
printf("%d\n", ans);
}
return 0;
}