HDU1853&&HDU3488(最小费用最大流)

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? 
InputThere 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). 
OutputOutput 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.

题意:给你N个点,M条有向边,让你连接n个环(点的个数>=2)使得花费最小,如果无法实现输出-1

思路:k个点组成一个环需要k条边,所以n个点无论组成多少个环都需要n条边,所以可以用最大流来判断是否有解,加上最小费用来求答案。源点为0,左部为1~n,右部为n+1~n*2,汇点会n*2+1。源点与左部每个点连接,右部每个点与汇点连接,对于每条有向边x与n+y连接。

这题有个坑点就是有重边(被坑n发。。。)

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
#define N 210
#define M 30410
#define inf 1000000007
typedef struct
{
    int u,v,w1,w2,next;
}Node;
Node e[M*2];
int head[N*2],vis[N*2],d[N*2],fa[N*2];
int n,m,tot,res;
int s[N][N];
void add(int x,int y,int z1,int z2)
{
    e[tot].u=x;
    e[tot].v=y;
    e[tot].w1=z1;
    e[tot].w2=z2;
    e[tot].next=head[x];
    head[x]=tot++;
}
int Spfa(int s,int t,int du)
{
    memset(vis,0,sizeof(vis));
    int i,j,u,x,y;
    for(i=0;i<=du;i++)
    {
        fa[i]=-1;
        d[i]=inf;
    }
    queue<int> q;
    d[s]=0;
    vis[s]=1;
    q.push(s);
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        vis[u]=0;
        for(i=head[u];i!=-1;i=e[i].next)
        {
            x=e[i].v;
            if(e[i].w1>0&&d[x]>d[u]+e[i].w2){
                d[x]=d[u]+e[i].w2;
                fa[x]=i;
                if(vis[x]==0)
                {
                    vis[x]=1;
                    q.push(x);
                }
            }
        }
    }
    if(fa[t]==-1)
        return 0;
    return 1;
}
int MCMF(int s,int t,int du)
{
    int ans=0,i,x,y=0;
    while(Spfa(s,t,du))
    {
        x=inf+1;
        for(i=fa[t];i!=-1;i=fa[e[i].u])
            x=min(x,e[i].w1);
        y=y+x;
        for(i=fa[t];i!=-1;i=fa[e[i].u])
        {
            e[i].w1-=x;
            e[i^1].w1+=x;
        }
        ans+=d[t]*x;
    }
    res=y;
    return ans;
}
int main()
{
    int i,j,k,t,x,y,z,ans;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        tot=0;
        memset(head,-1,sizeof(head));
        for(i=0;i<=n;i++)
        for(j=0;j<=n;j++)
            s[i][j]=inf;
        for(i=0;i<m;i++)
        {
            scanf("%d%d%d",&x,&y,&z);
            s[x][y]=min(s[x][y],z);
        }
        for(i=0;i<=n;i++)
        for(j=0;j<=n;j++)
        if(s[i][j]!=inf)
        {
            add(i,n+j,1,s[i][j]);
            add(n+j,i,0,-s[i][j]);
        }
        for(i=1;i<=n;i++)
        {
            add(0,i,1,0);
            add(i,0,0,0);
            add(n+i,n*2+1,1,0);
            add(n*2+1,n+i,0,0);
        }
        ans=MCMF(0,n*2+1,n*2+2);
        if(res!=n)
            printf("-1\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_37751662/article/details/80259861