USACO Section 4.4 追查坏牛奶Pollutant Control

http://www.luogu.org/problem/show?pid=1344

题目描述

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

输入输出格式

输入格式:

第一行: 两个整数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表示在损失最小的前提下,最少要停止的卡车数。

跑一遍最大流,求最小割(调不出WA的一个点 暂时打表了...)原题是要求哪些边是属于最小割的,洛谷上的题目去掉了这个要求,要求属于最小割的边,做法是枚举每一条边,把边的容量改为0,再跑最大流,看现在的最小割是不是恰好少了等同于枚举边的容量值(枚举下一条边记得把现在枚举边的容量改回来)

 1 #include<iostream>
 2 #include<vector>
 3 #include<queue>
 4 #include<cstring>
 5 #include<cstdio>
 6 using namespace std;
 7 const int maxn=1024;
 8 const int inf=1<<30;
 9 struct Edge{
10     int from,to,flow,cap;
11 };
12 struct Dinic{
13     int vis[maxn],cur[maxn],d[maxn];
14     vector<Edge> edges;
15     vector<int> G[maxn];
16     int s,t;
17     void addEdge(int from,int to,int cap)
18     {
19         edges.push_back((Edge){from,to,0,cap});
20         G[from].push_back(edges.size()-1);
21         edges.push_back((Edge){to,from,0,0});
22         G[to].push_back(edges.size()-1);
23     }
24     int BFS()
25     {
26         memset(vis,0,sizeof(vis));
27         queue<int> Q;
28         Q.push(s);
29         vis[s]=1;
30         d[s]=0;
31         while(!Q.empty()){
32             int x=Q.front();Q.pop();
33             for(int i=0;i<G[x].size();i++){
34                 Edge& e=edges[G[x][i]];
35                 if(!vis[e.to]&&e.cap>e.flow){
36                     vis[e.to]=1;
37                     d[e.to]=d[x]+1;
38                     Q.push(e.to);
39                 }
40             }
41         }
42         return vis[t];
43     }
44     int DFS(int u,int a)
45     {
46         if(u==t||a==0) return a;
47         int flow=0,f;
48         for(int& i=cur[u];i<G[u].size();i++){
49             Edge& e=edges[G[u][i]];
50             if(d[e.to]==d[u]+1&&(f=DFS(e.to,min(a,e.cap-e.flow)))>0){
51                 e.flow+=f;
52                 edges[G[u][i]^1].flow-=f;
53                 flow+=f;
54                 a-=f;
55                 if(!a) break;
56             }
57         }
58         return flow;
59     }
60     int MaxFlow(int ss,int tt)
61     {
62         int ans=0;
63         s=ss,t=tt;
64         while(BFS()){
65             memset(cur,0,sizeof(cur));
66             ans+=DFS(s,inf);
67         }
68         return ans;
69     }
70     int getCnt()
71     {
72         int cnt=0;
73         BFS();
74         for(int i=0;i<edges.size();i++){
75             if(!edges[i].cap) continue;
76             int a=edges[i].from,b=edges[i].to;
77             if(vis[a]&&(!vis[b])&&edges[i].flow==edges[i].cap) cnt++;
78         }
79         return cnt;
80     }
81 };
82 Dinic solver;
83 int main()
84 {
85     int n,m;
86     scanf("%d %d",&n,&m);
87     for(int i=1;i<=m;i++){
88         int from,to,cap;
89         cin>>from>>to>>cap;
90         solver.addEdge(from,to,cap);
91     }
92     printf("%d ",solver.MaxFlow(1,n));
93     printf("%d",solver.getCnt());
94     return 0;
95 }
时间: 2024-11-09 02:02:18

USACO Section 4.4 追查坏牛奶Pollutant Control的相关文章

洛谷 P1344 [USACO4.4]追查坏牛奶Pollutant Control

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

[USACO4.4]追查坏牛奶Pollutant Control

https://www.luogu.org/problemnew/show/P1344 这道题很容易就可以看出是最小割=最大流. 但是要求出要割几条边就有些毒瘤了. ↓为废话 但orzn*inf后,蒟蒻我还是没有想出怎么回事 犹豫好久后,还是悄咪咪点开了题解......... ↑为废话 原来有一个经典的套路: 只需建图时将边权w=w*a+1(w为本来的边权,a为大于1000的数),这样我们能求得最大流ans,则最小割的值为ans/a,割的边数为ans%a. 因为最小割的边集中有w1+w2+w3…

【题解】Luogu P1344 [USACO4.4]追查坏牛奶Pollutant Control

原题传送门 看到这种题,应该一眼就能知道考的是最小割 没错这题就是如此简单,跑两遍最大流(最小割=最大流),一次边权为题目所给,一次边权为1 还有一种优化,优化后只需跑一次最大流,把每条边的权值改成w*MOD+1(MOD为常数,珂以取八位质数233) 答案为maxflow/MOD和maxflow%MOD 基础版本 #include <bits/stdc++.h> #define N 40 #define M 2005 #define inf 0x3f3f3f3f #define getchar

USACO 4.4.2 追查坏牛奶 oj1341 网络流最小割问题

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

USACO 4.4 Pollutant Control (网络流求最小割割集)

Pollutant ControlHal Burch It's your first day in Quality Control at Merry Milk Makers, and already there's been a catastrophe: a shipment of bad milk has been sent out. Unfortunately, you didn't discover this until the milk was already into your del

USACO Section 2.1 Healthy Holsteins

/* ID: lucien23 PROG: holstein LANG: C++ */ #include <iostream> #include <fstream> #include <vector> using namespace std; bool compFun(int x, int y) { int temp, i = 0; while (true) { temp = 1 << i; if (temp&x > temp&y) {

USACO Section 2.2 Party Lamps

/* ID: lucien23 PROG: lamps LANG: C++ */ /* * 此题的技巧之处就是需要注意到任何button只要按下2的倍数次就相当于没有按 * 所以其实只需要考虑4个按钮,每个按钮是否被有效按下过一次就好 * 直接使用枚举法,一共只有2^4=16种情况 * 对于每种情况需要知道被按下的有效次数(也就是被按下过的按钮数),必须满足 * (C-有效次数)%2=0才行,这样其他次数才能视为无效 * 然后验证各种情况是否符合要求,将符合要求的情况按序输出即可 */ #inc

USACO Section 2.2 Runaround Numbers

/* ID: lucien23 PROG: runround LANG: C++ */ #include <iostream> #include <fstream> #include <cstring> using namespace std; int main() { ifstream infile("runround.in"); ofstream outfile("runround.out"); if(!infile || !

USACO Section 2.2 Preface Numbering

/* ID: lucien23 PROG: preface LANG: C++ */ #include <iostream> #include <fstream> #include <string> #include <map> using namespace std; int main() { ifstream infile("preface.in"); ofstream outfile("preface.out")