zoukankan      html  css  js  c++  java
  • hdu 1853 最小费用流好题 环的问题

    Cyclic Tour

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

    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
    RoBa@TJU
     
    Source
     
     
     
    题意:
    有n个点 m条边

    之后让这n个点组成多个环   使得每个点只能在一个环中    每个环最少2个点     

    求满足上面时  所有环的周长的和最小是多少

    思路:

    如果几个点构成一个环的话,那么这每一个点的入度与出度都是为1的  根据此  构造网络流图

    设一个源点0,汇点2*n+1,源点连接每一个u,容量为1,费用为0;汇点连接每一个v+n,容量也为1,费用为0;从u到v建一条边,容量为1,费用为w;那么这就转换成了最小费用最大流的模板题,假设最后最大流为n,那么说明恰好每一个点都是入度出度为1,即构成了环。

    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include<cmath>
    using namespace std;
    const int N=300;
    const int MAXE=200000;
    const int inf=1<<30;
    int head[N],ep;
    int d[N],pre[N];
    bool vis[N];
    int q[MAXE];
    struct Edge
    {
        int u,v,c,w,next;
    }edge[MAXE];
    void addedge(int u,int v,int w,int c)//u v 费用 容量
    {
        edge[ep].u=u;
        edge[ep].v=v;
        edge[ep].w=w;
        edge[ep].c=c;
        edge[ep].next=head[u];
        head[u]=ep++;
        edge[ep].v=u;
        edge[ep].u=v;
        edge[ep].w=-w;
        edge[ep].c=0;
        edge[ep].next=head[v];
        head[v]=ep++;
    }
    int SPFA(int src,int des)
    {
        int l,r;
        memset(pre,-1,sizeof(pre));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<=des;i++) d[i]=inf;
        d[src]=0;
        l=0;r=0;
        q[r++]=src;
        vis[src]=1;
        while(l<r)
        {
            int u=q[l++];
            vis[u]=0;
            for(int j=head[u];j!=-1;j=edge[j].next)
            {
                int v=edge[j].v;
                if(edge[j].c>0&&d[u]+edge[j].w<d[v])
                {
                    d[v]=d[u]+edge[j].w;
                    pre[v]=j;
                    if(!vis[v])
                    {
                        vis[v]=1;
                        q[r++]=v;
                    }
                }
            }
        }
        if(d[des]==inf)
            return 0;
        return 1;
    }
    int flow;
    int MCMF(int src,int des)
    {
        flow=0;int ans=0;
        while(SPFA(src,des))
        {
            ans+=d[des];
            int u=des;
            int mini=inf;
            while(u!=src)
            {
                if(edge[pre[u]].c<mini)
                    mini=edge[pre[u]].c;
                    u=edge[pre[u]].u;
            }
            flow+=mini;
            u=des;
            while(u!=src)
            {
                edge[pre[u]].c-=mini;
                edge[pre[u]^1].c+=mini;
                u=edge[pre[u]].u;
            }
        }
        return ans;
    }
    
    int main()
    {
        int n,m,i,src,des;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            ep=0;
            memset(head,-1,sizeof(head));
            src=0;
            des=2*n+1;
             while(m--)
             {
                 int v1,v2,w;
                  scanf("%d %d %d",&v1,&v2,&w);
                  addedge(v1,v2+n,w,1);
             }
             for(i=1;i<=n;i++)
             {
                //  addedge(i,i+n,0,1);
                 addedge(src,i,0,1);
                 addedge(i+n,des,0,1);
              }
    
                int ans=MCMF(src,des);
           if(flow==n)
              printf("%d
    ",ans);
            else printf("-1
    ");
        }
        return 0;
    }
    
    


     

     
  • 相关阅读:
    【彩彩只能变身队】后端工作总结
    彩彩只能变身队团队项目进展记录by后端
    一周工作+会议汇报(6.3)
    【彩彩只能变身队】第七次会议
    【彩彩只能变身队】第六次会议
    这个博客正式废用了!!!!搬家了!!!!
    [软件工程]一些不错的学习网站
    NWERC 2015 Problem H: Hole in One
    HDU 5970 CCPC2016合肥 求等差数列整除整数下取整求和
    [软件工程]python 发送邮件网易邮箱163示范
  • 原文地址:https://www.cnblogs.com/james1207/p/3281449.html
Copyright © 2011-2022 走看看