zoukankan      html  css  js  c++  java
  • hdu 3488

    题意:给出一个有向图,边带权,求一些环,使得每个点属于且仅属于一个环,幷最小化环边的权值和。

    思想和最小路径覆盖是一样的,将每个定点拆成两个点,假设u拆成u1,u2,那么所有边(v,u)对应新图中的(v1,u2),(u,v)对应(u1,v2)。

    然后会发现一种合法方案和新图(是一个二分图)的一个完美匹配一一对应。

    然后就可以用KM或网络流解决了。

    (这种有向图路径拆边的思想很漂亮)

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #include <vector>
     5 #define oo 0x3f3f3f3f
     6 #define maxn 410
     7 using namespace std;
     8 
     9 struct Edge {
    10     int u, v, c, f;
    11     Edge( int u, int v, int c, int f ):u(u),v(v),c(c),f(f){}
    12 };
    13 struct Mcmf {
    14     int n, src, dst;
    15     vector<Edge> edge;
    16     vector<int> g[maxn];
    17     int dis[maxn], ext[maxn], pth[maxn];
    18 
    19     void init( int nn, int s, int d ) {
    20         n = nn;
    21         src = s;
    22         dst = d;
    23         for( int i=1; i<=n; i++ )
    24             g[i].clear();
    25         edge.clear();
    26     }
    27     void add_edge( int u, int v, int c, int f ) {
    28         g[u].push_back( edge.size() );
    29         edge.push_back( Edge(u,v,c,f) );
    30         g[v].push_back( edge.size() );
    31         edge.push_back( Edge(v,u,-c,0) );
    32     }
    33     bool spfa( int &flow, int &cost ) {
    34         queue<int> qu;
    35         memset( dis, 0x3f, sizeof(dis) );
    36         qu.push( src );
    37         dis[src] = 0;
    38         ext[src] = true;
    39         pth[src] = -1;
    40         while( !qu.empty() ) {
    41             int u=qu.front();
    42             qu.pop();
    43             ext[u] = false;
    44             for( int t=0; t<g[u].size(); t++ ) {
    45                 Edge &e = edge[g[u][t]];
    46                 if( e.f && dis[e.v]>dis[e.u]+e.c ) {
    47                     dis[e.v] = dis[e.u]+e.c;
    48                     pth[e.v] = g[u][t];
    49                     if( !ext[e.v] ) {
    50                         ext[e.v] = true;
    51                         qu.push( e.v );
    52                     }
    53                 }
    54             }
    55         }
    56         if( dis[dst]==oo ) return false;
    57         int flw = oo;
    58         for( int eid=pth[dst]; eid!=-1; eid=pth[edge[eid].u] ) 
    59             flw = min( flw, edge[eid].f );
    60         for( int eid=pth[dst]; eid!=-1; eid=pth[edge[eid].u] ) {
    61             edge[eid].f -= flw;
    62             edge[eid^1].f += flw;
    63         }
    64         flow += flw;
    65         cost += flw*dis[dst];
    66         return true;
    67     }
    68     void mcmf( int &flow, int &cost ) {
    69         flow = cost = 0;
    70         while( spfa(flow,cost) );
    71     }
    72 };
    73 
    74 int n, m;
    75 Mcmf M;
    76 
    77 int main() {
    78     int T;
    79     scanf( "%d", &T );
    80     while(T--) {
    81         scanf( "%d%d", &n, &m );
    82         int tot = n+n+2;
    83         M.init( tot, tot-1, tot );
    84         for( int i=1,u,v,w; i<=m; i++ ) {
    85             scanf( "%d%d%d", &u, &v, &w );
    86             M.add_edge( u, v+n, w, 1 );
    87         }
    88         for( int u=1; u<=n; u++ ) {
    89             M.add_edge( M.src, u, 0, 1 );
    90             M.add_edge( u+n, M.dst, 0, 1 );
    91         }
    92         int flow, cost;
    93         M.mcmf(flow,cost);
    94         printf( "%d
    ", cost );
    95     }
    96 }
    View Code
  • 相关阅读:
    从带Per-Building数据的KML/COLLADA中创建3D Tiles
    将Cesium Tools用于更好的构建管理
    使用Cesium Stories在3D Tilesets中检查Features
    使用Cesium Stories来可视化时序数据
    使用3D Tiles Overview学习3D Tiles
    使用EdgyGeo Cesium工具查询下载数据集
    探索新冠肺炎(COVID-19)对全球航班的影响
    [一]Cesium利其器——Visual Studio Code
    Cesium中文网的朋友们
    Gym 101908C
  • 原文地址:https://www.cnblogs.com/idy002/p/4320978.html
Copyright © 2011-2022 走看看