天天看點

Cyclic Tour hdu 1853 最小費用最最大流 Cyclic Tour

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

這個題目應該講其實是很不錯的,但是我現在覺得建圖真是一個大問題,因為實在想不到為什麼這樣建圖,這樣很是無奈的,唉,還是 做題目太少了

Cyclic Tour hdu 1853 最小費用最最大流 Cyclic Tour
Cyclic Tour hdu 1853 最小費用最最大流 Cyclic Tour

這就是建圖的結果,然後我們用最大流和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;
}