zoukankan      html  css  js  c++  java
  • 洛谷 P1344 [USACO4.4]追查坏牛奶Pollutant Control

    题目描述

    你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶。很不幸,你发现这件事的时候,有三聚氰胺的牛奶已经进入了送货网。这个送货网很大,而且关系复杂。你知道这批牛奶要发给哪个零售商,但是要把这批牛奶送到他手中有许多种途径。送货网由一些仓库和运输卡车组成,每辆卡车都在各自固定的两个仓库之间单向运输牛奶。在追查这些有三聚氰胺的牛奶的时候,有必要保证它不被送到零售商手里,所以必须使某些运输卡车停止运输,但是停止每辆卡车都会有一定的经济损失。你的任务是,在保证坏牛奶不送到零售商的前提下,制定出停止卡车运输的方案,使损失最小。

    输入输出格式

    输入格式:

    第一行: 两个整数N(2<=N<=32)、M(0<=M<=1000), N表示仓库的数目,M表示运输卡车的数量。仓库1代 表发货工厂,仓库N代表有三聚氰胺的牛奶要发往的零售商。 第2..M+1行: 每行3个整数Si,Ei,Ci。其中Si,Ei表示这 辆卡车的出发仓库,目的仓库。Ci(0 <= C i <= 2,000,000) 表示让这辆卡车停止运输的损失。

    输出格式:

    两个整数C、T:C表示最小的损失,T表示在损失最小的前提下,最少要停止的卡车数。

    输入输出样例

    输入样例#1: 
    4 5
    1 3 100
    3 2 50
    2 4 60
    1 2 40
    2 3 80
    
    输出样例#1: 
    60 1
    

    说明

    题目翻译来自NOCOW。

    USACO Training Section 4.4

    Solution:

      简单讲,本题给出了边的权值,要求最小的代价使得1和n不连通。这不就是最小割嘛!我们直接把1当作S,n当作T。

      但因为本题既要输出最小割的值又要输出割的边数,前者好求关键是后者如何去求更简单,容易想到我们可以直接建两次图,一次按原边权建图跑最大流求得最小割,再按边权为1建图跑最大流求割的边数,这是一种思路;

      当然我们完全可以换种思路用一次最大流搞定,只需建图时将边权w=w*a+1(w为本来的边权,a为大于1000的数),这样我们能求得最大流ans,则最小割的值为ans/a,割的边数为ans%a。这很容易理解,但是还是解释一下:因为最小割的边集中有w1+w2+w3…+wn=ans(这个ans为本来的最小割),所以必然有w1*a+w2*a+w3*a…+wn*a=ans*a,于是必然有w1*a+1+w2*a+1+w3*a+1…+wn*a+1=ans*a+k(k为最小割的边数,k<=m<=1000),这样就很明显了,因为边数m不大于1000,所以k的最大值为1000,我们只要使设定的a的值大于1000,那么按上述方法建图,跑出的最大流除以a就是最小割的值ans,最大流模a就是最小割的边数k。

    代码:

     1 // luogu-judger-enable-o2
     2 #include<bits/stdc++.h>
     3 #define il inline
     4 #define ll long long 
     5 #define debug printf("%d %s
    ",__LINE__,__FUNCTION__)
     6 using namespace std;
     7 const ll N=100005,inf=233333333333333,mod=2018;
     8 ll n,m,s,t,h[100],dis[2005],cnt=1;
     9 ll ans;
    10 struct edge{
    11 ll to,net;ll v;
    12 }e[N];
    13 il void add(ll u,ll v,ll w)
    14 {
    15     e[++cnt].to=v,e[cnt].net=h[u],e[cnt].v=w,h[u]=cnt;
    16     e[++cnt].to=u,e[cnt].net=h[v],e[cnt].v=0,h[v]=cnt;
    17 }
    18 queue<ll>q;
    19 il bool bfs()
    20 {
    21     memset(dis,-1,sizeof(dis));
    22     q.push(s),dis[s]=0;
    23     while(!q.empty())
    24     {
    25         int u=q.front();q.pop();
    26         for(int i=h[u];i;i=e[i].net)
    27         if(dis[e[i].to]==-1&&e[i].v>0)dis[e[i].to]=dis[u]+1,q.push(e[i].to);
    28     }
    29     return dis[t]!=-1;
    30 }
    31 il ll dfs(ll u,ll op)
    32 {
    33     if(u==t)return op;
    34     ll flow=0,used=0;
    35     for(int i=h[u];i;i=e[i].net)
    36     {
    37         int v=e[i].to;
    38         if(dis[v]==dis[u]+1&&e[i].v>0)
    39         {
    40             used=dfs(v,min(op,e[i].v));
    41             if(!used)continue;
    42             flow+=used,op-=used;
    43             e[i].v-=used,e[i^1].v+=used;
    44             if(!op)break;
    45         }
    46     }
    47     if(!flow)dis[u]=-1;
    48     return flow;
    49 }
    50 int main()
    51 {
    52     scanf("%lld%lld",&n,&m);s=1,t=n;
    53     ll u,v;ll w;
    54     for(int i=1;i<=m;i++)
    55     {
    56         scanf("%lld%lld%lld",&u,&v,&w);
    57         add(u,v,w*mod+1);
    58     }
    59     while(bfs())ans+=dfs(s,inf);
    60     printf("%lld %lld
    ",ans/mod,ans%mod);
    61     return 0;
    62 }
  • 相关阅读:
    HDU4474 Yet Another Multiple Problem BFS搜索
    HDU4473 Exam 数学分析
    2013ACM多校联合(4)
    POJ1273 网络流...
    HDU4472 Count 递推
    POJ1149 PIGS 网络流
    UVA10881 Piotr's Ants 想法题
    javascript js string.Format()收集
    修改 设置 vs.net 网站 调试 设为 起始页
    【转】HTML5杂谈 概念与现行游戏 割绳子 宝石迷阵
  • 原文地址:https://www.cnblogs.com/five20/p/8284477.html
Copyright © 2011-2022 走看看