• HDU 3488 Tour


    题意:给出一张有n个点m条边带权的有向图,要你找出若干个回路并且使得所有的点都在某个回路上,且所有的点只能出现在一个回路中,求由n条边组成的若干回路的最小权值。

    所有点只能出现在一个回路中,因此,所有的点都对应唯一的前驱或后继,因此这就是一个匹配问题。如果有边(u->v),边权为w,那它就对应二分图中的一条边(u,v',w),直接这样建图跑KM就可以了。当然,用这种写法的费用流会比较慢。

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <cstring>
     4 #include <queue>
     5 #define maxn 410
     6 #define maxm 70000
     7 #define INF 1<<30
     8 using namespace std;
     9 struct MCMF{
    10     int src,sink,e,n;
    11     int first[maxn];
    12     int cap[maxm],cost[maxm],v[maxm],next[maxm];
    13     bool flag;
    14     void init(){
    15         e = 0;
    16         memset(first,-1,sizeof(first));
    17     }
    18 
    19     void add_edge(int a,int b,int cc,int ww){
    20         cap[e] = cc;cost[e] = ww;v[e] = b;
    21         next[e] = first[a];first[a] = e++;
    22         cap[e] = 0;cost[e] = -ww;v[e] = a;
    23         next[e] = first[b];first[b] = e++;
    24     }
    25 
    26     int d[maxn],pre[maxn],pos[maxn];
    27     bool vis[maxn];
    28 
    29     bool spfa(int s,int t){
    30         memset(pre,-1,sizeof(pre));
    31         memset(vis,0,sizeof(vis));
    32         queue<int> Q;
    33         for(int i = 0;i <= n;i++)   d[i] = INF;
    34         Q.push(s);pre[s] = s;d[s] = 0;vis[s] = 1;
    35         while(!Q.empty()){
    36             int u = Q.front();Q.pop();
    37             vis[u] = 0;
    38             for(int i = first[u];i != -1;i = next[i]){
    39                 if(cap[i] > 0 && d[u] + cost[i] < d[v[i]]){
    40                     d[v[i]] = d[u] + cost[i];
    41                     pre[v[i]] = u;pos[v[i]] = i;
    42                     if(!vis[v[i]])  vis[v[i]] = 1,Q.push(v[i]);
    43                 }
    44             }
    45         }
    46         return pre[t] != -1;
    47     }
    48 
    49     int Mincost;
    50     int Maxflow;
    51 
    52     int MinCostFlow(int s,int t,int nn){
    53         Mincost = 0,Maxflow = 0,n = nn;
    54         while(spfa(s,t)){
    55             int min_f = INF;
    56             for(int i = t;i != s;i = pre[i])
    57                 if(cap[pos[i]] < min_f) min_f = cap[pos[i]];
    58             Mincost += d[t] * min_f;
    59             Maxflow += min_f;
    60             for(int i = t;i != s;i = pre[i]){
    61                 cap[pos[i]] -= min_f;
    62                 cap[pos[i]^1] += min_f;
    63             }
    64         }
    65         return Mincost;
    66     }
    67 };
    68 MCMF g;
    69 int main()
    70 {
    71     int n,m,t;
    72     scanf("%d",&t);
    73     while(t--){
    74         scanf("%d%d",&n,&m);
    75         g.init();
    76         int S = 0,T = 2*n+1;
    77         for(int i = 1;i <= n;i++)
    78             g.add_edge(S,i,1,0),g.add_edge(i+n,T,1,0);
    79         for(int i = 0;i < m;i++){
    80             int a,b,c;
    81             scanf("%d%d%d",&a,&b,&c);
    82             g.add_edge(a,b+n,1,c);
    83         }
    84         printf("%d
    ",g.MinCostFlow(S,T,T));
    85     }
    86     return 0;
    87 }
    View Code
  • 相关阅读:
    js中Math.random()生成指定范围数值的随机数【转】
    JS绘制生成花瓣效果的方法【转】
    php 解决json_encode中文UNICODE转码问题【转】
    JS/JQuery获取当前元素的上一个/下一个兄弟级元素等元素的方法【转】
    PHP数据类型转换(字符转数字,数字转字符)【转】
    PHP 数组转字符串,与字符串转数组【转】
    js中forEach,for in,for of循环的用法【转】
    layui下的checkbox用js如何选中它【转】
    js数组与字符串的相互转换方法【转】
    JS判断网页是否为手机打开【转】
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3407284.html
Copyright © 2020-2023  润新知