Problem Description

Open Source Tools help earthquake researchers stay a step ahead. Many geological research facilities around the world use or are in the process of developing open source software and applications designed to interpret and share information with other researchers. For example, OpenSees is an open source software framework for developing apps that help understand what happens to structures during and after earthquakes to help engineers design stronger buildings. Researchers are also using OpenSees to understand the potential ill-effects of seismic activity on viaducts and bridges.

China has had an earthquake that has struck Sichuan Province on Monday 12 May 2008!

The earthquake has damaged some of the cities so that they are unpassable. Remarkably, after repairing by Chinese People's Liberation Army, all the driveways between cities were fixed.

As usual, Sichuan Province is modeled as a set of P (1 <= P <= 3,000) cities conveniently numbered 1..P which are connected by a set of C (1 <= C <= 20,000) non-directional driveways conveniently numbered 1..C. Driveway i connects city a_i and b_i (1 <= a_i <= P; 1 <= b_i <= P). Driveway might connect a_i to itself or perhaps might connect two cities more than once. The Crisis Center is located in city 1.

A total of N (1 <= N <= P) survivors (in different cities) sequentially contacts Crisis Center via moobile phone with an integer message report_j (2 <= report_j <= P) that indicates that city report_j is undamaged but that the calling survivor is unable to return to the Crisis Center from city report_j because he/she could not find a path that does not go through damaged city.

After all the survivors report in, determine the minimum number of cities that are damaged.

 Input

Input consists of several testcases. The format of each case as follow:

  • Line 1: Three space-separated integers: P, C, and N
  • Lines 2..C+1: Line i+1 describes cowpath i with two integers: a_i and b_i
  • Lines C+2..C+N+1: Line C+1+j contains a single integer: report_j

 Output

For each testcase, output a line with one number, the minimum number of damaged cities.

用最大流最小割定理,最大流=最小割,很久以前做的,题目已忘,我是来放模版的

DINIC算法+当前弧优化+有容量上限,78MS

 #include <cstdio>
#include <cstring>
#include <queue>
using namespace std; #define MAXN 6010
#define MAXM 100010 #define INF 0x7fffffff struct Dinic {
int n, m, st, ed, ecnt;
int vis[MAXN], head[MAXN];
int cur[MAXN], d[MAXN];
int to[MAXM], next[MAXM], flow[MAXM], cap[MAXM]; void init(int ss, int tt){
memset(head,,sizeof(head));
ecnt = ;
st = ss; ed = tt;
} void addEdge(int u,int v,int c) {
//flow[ecnt] = c
to[ecnt] = v; cap[ecnt] = c; flow[ecnt] = ; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; cap[ecnt] = ; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
} bool bfs() {
memset(vis, , sizeof(vis));
queue<int> que; que.push(st);
d[st] = ; vis[st] = true;
while(!que.empty()){
int u = que.front(); que.pop();
for(int p = head[u]; p; p = next[p]){
int v = to[p];
if (!vis[v] && cap[p] > flow[p]){//flow[p] > 0
vis[v] = ;
d[v] = d[u] + ;
que.push(v);
if(v == ed) return true;
}
}
}
return vis[ed];
} int dfs(int u, int a) {
if(u == ed || a == ) return a;
int outflow = , f;
for(int &p = cur[u]; p; p = next[p]){
int v = to[p];
if(d[u] + == d[v] && (f = dfs(v, min(a, cap[p] - flow[p]))) > ){//min(a, flow[p])
flow[p] += f;//flow[p] -= f;
flow[p ^ ] -= f;//flow[p ^ 1] += f;
outflow += f;
a -= f;
if(a == ) break;
}
}
return outflow;
} int Maxflow() {
int ans = ;
while(bfs()){
for(int i = ; i <= ed; ++i) cur[i] = head[i];
ans += dfs(st, INF);
}
return ans;
}
} G; int vis[MAXN]; int main() {
int ss, tt, N, C, P;
while(scanf("%d%d%d",&P,&C,&N)!=EOF){
ss = ; tt = *P+;
G.init(ss, tt);
while(C--){
int a, b;
scanf("%d%d",&a,&b);
G.addEdge(a + P, b, INF);
G.addEdge(b + P, a, INF);
}
memset(vis, , sizeof(vis));
while(N--){
int x;
scanf("%d",&x);
G.addEdge(x, tt, INF);
vis[x] = ;
}
for(int i = ; i <= P; ++i){
if(i != && !vis[i]) G.addEdge(i, i + P, );
else G.addEdge(i, i + P, INF);
}
G.n = tt;
printf("%d\n",G.Maxflow());
}
return ;
}

DINIC算法+当前弧优化+只有余量,62MS

 #include <cstdio>
#include <cstring>
#include <queue>
using namespace std; #define MAXN 6010
#define MAXM 100010 #define INF 0x7fffffff struct Dinic {
int n, m, st, ed, ecnt;
int vis[MAXN], head[MAXN];
int cur[MAXN], d[MAXN];
int to[MAXM], next[MAXM], flow[MAXM]; void init(int ss, int tt){
memset(head,,sizeof(head));
ecnt = ;
st = ss; ed = tt;
} void addEdge(int u,int v,int f) {
to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
} bool bfs() {
memset(vis, , sizeof(vis));
queue<int> que; que.push(st);
d[st] = ; vis[st] = true;
while(!que.empty()){
int u = que.front(); que.pop();
for(int p = head[u]; p; p = next[p]){
int v = to[p];
if (!vis[v] && flow[p] > ){
vis[v] = ;
d[v] = d[u] + ;
que.push(v);
if(v == ed) return true;
}
}
}
return vis[ed];
} int dfs(int u, int a) {
if(u == ed || a == ) return a;
int outflow = , f;
for(int &p = cur[u]; p; p = next[p]){
int v = to[p];
if(d[u] + == d[v] && (f = dfs(v, min(a, flow[p]))) > ){
flow[p] -= f;
flow[p ^ ] += f;
outflow += f;
a -= f;
if(a == ) break;
}
}
return outflow;
} int Maxflow() {
int ans = ;
while(bfs()){
for(int i = ; i <= ed; ++i) cur[i] = head[i];
ans += dfs(st, INF);
}
return ans;
}
} G; int vis[MAXN]; int main() {
int ss, tt, N, C, P;
while(scanf("%d%d%d",&P,&C,&N)!=EOF){
ss = ; tt = *P+;
G.init(ss, tt);
while(C--){
int a, b;
scanf("%d%d",&a,&b);
G.addEdge(a + P, b, INF);
G.addEdge(b + P, a, INF);
}
memset(vis, , sizeof(vis));
while(N--){
int x;
scanf("%d",&x);
G.addEdge(x, tt, INF);
vis[x] = ;
}
for(int i = ; i <= P; ++i){
if(i != && !vis[i]) G.addEdge(i, i + P, );
else G.addEdge(i, i + P, INF);
}
G.n = tt;
printf("%d\n",G.Maxflow());
}
return ;
}

ISAP算法,78MS(把注释删掉再交一次又变成了93MS,OJ的时间果然信不过o(╯□╰)o)//不能有点0

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; #define MAXN 6010
#define MAXM 100010
#define INF 0x7fffffff struct SAP {
int vis[MAXN], head[MAXN];
int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
int to[MAXM], flow[MAXM], next[MAXM];
int ecnt, st, ed; void init(int ss, int tt) {
memset(head, , sizeof(head));
ecnt = ;
st = ss; ed = tt;
} void addEdge(int u,int v,int f) {
to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
} int Max_flow() {
int ans = , minFlow = INF, n = ed, u;
for (int i = ; i <= n; ++i){
cur[i] = head[i];
gap[i] = dis[i] = ;
}
u = pre[st] = st;
gap[] = n;
while (dis[st] < n){
bool flag = false;
for (int &p = cur[u]; p; p = next[p]){
int v = to[p];
if (flow[p] > && dis[u] == dis[v] + ){
flag = true;
minFlow = min(minFlow, flow[p]);
pre[v] = u;
u = v;
if(u == ed){
ans += minFlow;
while (u != st){
u = pre[u];
flow[cur[u]] -= minFlow;
flow[cur[u] ^ ] += minFlow;
}
minFlow = INF;
}
break;
}
}
if (flag) continue;
int minDis = n-;
for (int p = head[u]; p; p = next[p]){
int v = to[p];
if (flow[p] && dis[v] < minDis){
minDis = dis[v];
cur[u] = p;
}
}
if (--gap[dis[u]] == ) break;
gap[dis[u] = minDis+]++;
u = pre[u];
}
return ans;
}
} G; bool vis[MAXN]; int main() {
int ss, tt, N, C, P;
while(scanf("%d%d%d",&P,&C,&N)!=EOF) {
ss = ; tt = *P+;
G.init(ss, tt);
while(C--) {
int a, b;
scanf("%d%d",&a,&b);
G.addEdge(a + P, b, INF);
G.addEdge(b + P, a, INF);
}
memset(vis, , sizeof(vis));
while(N--) {
int x;
scanf("%d",&x);
G.addEdge(x, tt, INF);
vis[x] = ;
}
for(int i = ; i <= P; ++i) {
if(i != && !vis[i]) G.addEdge(i, i + P, );
else G.addEdge(i, i + P, INF);
}
printf("%d\n",G.Max_flow());
}
return ;
}

ISAP算法+BFS初始化,62MS(SGU 438把我这模板跑跪了,现在换掉了>_<)//不能有点0

 #include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std; #define MAXN 6010
#define MAXM 100010
#define INF 0x7fffffff struct SAP {
int head[MAXN];
int gap[MAXN], dis[MAXN], pre[MAXN], cur[MAXN];
int to[MAXM], flow[MAXM], next[MAXM];
int ecnt, st, ed, n; void init(int ss, int tt, int nn) {
memset(head, , sizeof(head));
ecnt = ;
st = ss; ed = tt; n = nn;
} void addEdge(int u,int v,int f) {
to[ecnt] = v; flow[ecnt] = f; next[ecnt] = head[u]; head[u] = ecnt++;
to[ecnt] = u; flow[ecnt] = ; next[ecnt] = head[v]; head[v] = ecnt++;
} void bfs() {
memset(dis, 0x3f, sizeof(dis));
queue<int> que; que.push(ed);
dis[ed] = ;
while(!que.empty()) {
int u = que.front(); que.pop();
++gap[dis[u]];
for(int p = head[u]; p; p = next[p]) {
int v = to[p];
if (dis[v] > ed && flow[p ^ ] > ) {
dis[v] = dis[u] + ;
que.push(v);
}
}
}
} int Max_flow() {
int ans = , minFlow = INF, u;
for (int i = ; i <= n; ++i){
cur[i] = head[i];
gap[i] = dis[i] = ;
}
u = pre[st] = st;
//gap[0] = n;
bfs();
while (dis[st] < n){
bool flag = false;
for (int &p = cur[u]; p; p = next[p]){
int v = to[p];
if (flow[p] > && dis[u] == dis[v] + ){
flag = true;
minFlow = min(minFlow, flow[p]);
pre[v] = u;
u = v;
if(u == ed){
ans += minFlow;
while (u != st){
u = pre[u];
flow[cur[u]] -= minFlow;
flow[cur[u] ^ ] += minFlow;
}
minFlow = INF;
}
break;
}
}
if (flag) continue;
int minDis = n-;
for (int p = head[u]; p; p = next[p]){
int v = to[p];
if (flow[p] && dis[v] < minDis){
minDis = dis[v];
cur[u] = p;
}
}
if (--gap[dis[u]] == ) break;
gap[dis[u] = minDis+]++;
u = pre[u];
}
return ans;
}
} G; bool vis[MAXN]; int main() {
int ss, tt, N, C, P;
while(scanf("%d%d%d",&P,&C,&N)!=EOF) {
ss = ; tt = *P+;
G.init(ss, tt, tt);
while(C--) {
int a, b;
scanf("%d%d",&a,&b);
G.addEdge(a + P, b, INF);
G.addEdge(b + P, a, INF);
}
memset(vis, , sizeof(vis));
while(N--) {
int x;
scanf("%d",&x);
G.addEdge(x, tt, INF);
vis[x] = ;
}
for(int i = ; i <= P; ++i) {
if(i != && !vis[i]) G.addEdge(i, i + P, );
else G.addEdge(i, i + P, INF);
}
printf("%d\n",G.Max_flow());
}
return ;
}

FZU 1844 Earthquake Damage(最大流最小割)的更多相关文章

  1. bzoj 1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害

    1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害 Description Farmer John的农场里有P个牧场,有C条无向道路连接着他们,第i条道路连接着 ...

  2. hiho 第116周,最大流最小割定理,求最小割集S,T

    小Hi:在上一周的Hiho一下中我们初步讲解了网络流的概念以及常规解法,小Ho你还记得内容么? 小Ho:我记得!网络流就是给定了一张图G=(V,E),以及源点s和汇点t.每一条边e(u,v)具有容量c ...

  3. hihocoder 网络流二·最大流最小割定理

    网络流二·最大流最小割定理 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi:在上一周的Hiho一下中我们初步讲解了网络流的概念以及常规解法,小Ho你还记得内容么? ...

  4. [HihoCoder1378]网络流二·最大流最小割定理

    思路: 根据最大流最小割定理可得最大流与最小割相等,所以可以先跑一遍EdmondsKarp算法.接下来要求的是经过最小割切割后的图中$S$所属的点集.本来的思路是用并查集处理所有前向边构成的残量网络, ...

  5. HDU 1569 方格取数(2)(最大流最小割の最大权独立集)

    Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大.   ...

  6. 【codevs1907】方格取数3(最大流最小割定理)

    网址:http://codevs.cn/problem/1907/ 题意:在一个矩阵里选不相邻的若干个数,使这些数的和最大. 我们可以把它看成一个最小割,答案就是矩阵中的所有数-最小割.先把矩阵按国际 ...

  7. 洛谷 P2932 [USACO09JAN]地震造成的破坏Earthquake Damage

    P2932 [USACO09JAN]地震造成的破坏Earthquake Damage 题目描述 Wisconsin has had an earthquake that has struck Farm ...

  8. 紫书 例题 11-12 UVa 1515 (最大流最小割)

    这道题要分隔草和洞, 然后刘汝佳就想到了"割"(不知道他怎么想的, 反正我没想到) 然后就按照这个思路走, 网络流建模然后求最大流最小割. 分成两部分, S和草连, 洞和T连 外围 ...

  9. HDU-4289-Control(最大流最小割,拆点)

    链接: https://vjudge.net/problem/HDU-4289 题意: You, the head of Department of Security, recently receiv ...

随机推荐

  1. vector 定义的二维数组的遍历

    之前我们分享了STL的一些容器,再介绍vector中只介绍了二维的vector的定义并没有说二维的vector怎么遍历,那么我们今天就来看下二维的vector怎么遍历 看下面的代码吧. #includ ...

  2. linux系统基础之-----磁盘结构(基于centos7.4 1708)

  3. 使用PHPExcel 对表格进行,读取和写入的操作。。。。

    下面的代码是使用PHPExcel 对多个表格数据进行读取, 然后整合的写入新的表格的方法!!!代码有点粗糙 , 多多保函!!! 这里有些地方注意下,如果你的表格数据过大, 一定要记得修改php.ini ...

  4. MapReduce序列化及分区的java代码示例

    概述 序列化(Serialization)是指把结构化对象转化为字节流. 反序列化(Deserialization)是序列化的逆过程.把字节流转为结构化对象. 当要在进程间传递对象或持久化对象的时候, ...

  5. django创建第一个子应用-3

    在Web应用中,通常有一些业务功能模块是在不同的项目中都可以复用的,故在开发中通常将工程项目拆分为不同的子功能模块,各功能模块间可以保持相对的独立,在其他工程项目中需要用到某个特定功能模块时,可以将该 ...

  6. phpcms v9 完美更换整合Ueditor 1.3

    phpcms这套系统相信大家不陌生,它做的很不错,但是也有好多地方不满足我们的需求,比如在线编辑器. 它自带的是CKEditor编辑器,功能较少,比如代码加亮功能就没有. 所以我来说一下怎么替换php ...

  7. pyhton新手学习之增删改查

    一 .列表的定义 1.列表的定义     names = [ "xiajiqni", "test", "wangwu","oldb ...

  8. python教程(二)·数据结构初探

    这一节,我来简单讲讲python自带的数据结构. 列表(list) 列表是常用的python数据结构,类似于C语言的数组,用来存储多个元素,与之不同的是,C语言的数组中的元素的类型是相同的,而列表可以 ...

  9. Java8 Comparator 排序方法

    Java8 中 Comparator 接口提供了一些静态方法,可以方便于我们进行排序操作,下面通过例子讲解下如何使用 对整数列表排序(升序) List<Integer> list = Ar ...

  10. gsl 复数

    一.复数的表示 复数的两种表示: gsl复数结构的声明和部分宏在gsl_complex.h中,方法的声明和另一部分宏在gsl_complex_math.h.复数的表示(结构)有三种,即float型.d ...