zoukankan      html  css  js  c++  java
  • hdu 1853 Cyclic Tour 最小费用最大流

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1853

    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?
     
    题意描述:n个城市里有m条单向路径,每条路径上有一个权值,每个城市都属于且仅属于某一个环,Tom计划环游这n个城市,并且每个城市都只能经过一次。问最后环游了n个城市后最小的权值和是多少。
    算法分析:费用流的常见模型,对于初学费用流的我来说,还是挺新鲜的,也参考了其他ACMer的博客。
    首先提取出模型:给定一个有向图,要求用若干个环覆盖整个图,并且覆盖的这些环的权值和最小。
    建模:源点from和汇点to,拆点 i 为 i 和 i+n。 from->i(w为1,cost为0)(w为1是因为每个城市只能游历一次),i+n->to(w为1,cost为0),对于u->v,连接u->v+n(w为1,cost为路径上的权值)。
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cstdlib>
      5 #include<cmath>
      6 #include<algorithm>
      7 #include<queue>
      8 #define inf 0x7fffffff
      9 using namespace std;
     10 const int maxn=200+10;
     11 const int M = 40000+100;
     12 
     13 int n,m,from,to;
     14 struct node
     15 {
     16     int v,flow,cost;
     17     int next;
     18 }edge[M*3];
     19 int head[maxn],edgenum;
     20 int dis[maxn],pre[maxn],pid[maxn],vis[maxn];
     21 int Maxflow;
     22 
     23 void add(int u,int v,int flow,int cost)
     24 {
     25     edge[edgenum].v=v ;edge[edgenum].flow=flow ;
     26     edge[edgenum].cost=cost ;edge[edgenum].next=head[u];
     27     head[u]=edgenum++;
     28 
     29     edge[edgenum].v=u ;edge[edgenum].flow=0;
     30     edge[edgenum].cost=-cost ;edge[edgenum].next=head[v];
     31     head[v]=edgenum++;
     32 }
     33 
     34 int spfa()
     35 {
     36     for (int i=1 ;i<=to ;i++) dis[i]=inf;
     37     memset(vis,0,sizeof(vis));
     38     queue<int> Q;
     39     Q.push(from);
     40     dis[from]=0;
     41     vis[from]=1;
     42     while (!Q.empty())
     43     {
     44         int u=Q.front() ;Q.pop() ;
     45         vis[u]=0;
     46         for (int i=head[u] ;i!=-1 ;i=edge[i].next)
     47         {
     48             int v=edge[i].v;
     49             if (edge[i].flow>0 && dis[v]>dis[u]+edge[i].cost)
     50             {
     51                 dis[v]=dis[u]+edge[i].cost;
     52                 pre[v]=u;
     53                 pid[v]=i;
     54                 if (!vis[v])
     55                 {
     56                     vis[v]=1;
     57                     Q.push(v);
     58                 }
     59             }
     60         }
     61     }
     62     return dis[to];
     63 }
     64 
     65 int mincost()
     66 {
     67     int ans=0,maxflow=0;
     68     int aug=0;
     69     while (1)
     70     {
     71         aug=inf;
     72         int tmp=spfa();
     73         if (tmp==inf) break;
     74         for (int i=to ;i!=from ;i=pre[i])
     75         {
     76             if (edge[pid[i] ].flow<aug)
     77                 aug=edge[pid[i] ].flow;
     78         }
     79         for (int i=to ;i!=from ;i=pre[i])
     80         {
     81             edge[pid[i] ].flow -= aug;
     82             edge[pid[i]^1 ].flow += aug;
     83         }
     84         maxflow += aug;
     85         ans += tmp*aug;
     86     }
     87     Maxflow=maxflow;
     88     return ans;
     89 }
     90 
     91 int main()
     92 {
     93     while (scanf("%d%d",&n,&m)!=EOF)
     94     {
     95         memset(head,-1,sizeof(head));
     96         edgenum=0;
     97         int a,b,c;
     98         from=2*n+1;
     99         to=from+1;
    100         Maxflow=0;
    101         for (int i=0 ;i<m ;i++)
    102         {
    103             scanf("%d%d%d",&a,&b,&c);
    104             add(a,b+n,1,c);
    105         }
    106         for (int i=1 ;i<=n ;i++)
    107         {
    108             add(from,i,1,0);
    109             add(i+n,to,1,0);
    110         }
    111         int ans=mincost();
    112         printf("%d
    ",Maxflow==n ? ans : -1);
    113     }
    114     return 0;
    115 }
  • 相关阅读:
    Oracle-学习笔记(==》集合函数与分组四)
    Mysql--学习笔记(==》简单查询三)
    Mysql-学习笔记(==》插入修改数据二)
    Mysql-学习笔记(==》建表修改一)
    EasyUI的DataGrid 打印导出
    SQL 中ROLLUP 用法
    easyui commbox嵌入一个checkbox的实现
    Easyui Layout Center 全屏方法扩展
    Datagrid扩展方法InitEditGrid{支持单元格编辑}
    Datagrid扩展方法onClickCell{easyui-datagrid-扩充-支持单元格编辑}
  • 原文地址:https://www.cnblogs.com/huangxf/p/4334122.html
Copyright © 2011-2022 走看看