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. 高性能mysql:创建高性能的索引

    本文系阅读<高性能MySQL>,Baron Schwartz等著一书中第五章 创建高性能的索引的笔记,索引是存储引擎用于快速找到记录的一种数据结构. 索引对于良好的性能非常关键,尤其是当表 ...

  2. sysbench安装

    sysbench安装 1.下载软件mkdir -p /usr/local/softwarecd /usr/local/softwaregit clone https://github.com/akop ...

  3. Spring Boot 微信-验证服务器有效性【转】

    转:https://blog.csdn.net/jeikerxiao/article/details/68064145 概述 接入微信公众平台开发,开发者需要按照如下步骤完成: 在自己服务器上,开发验 ...

  4. jQuery的简单函数

    1. jQuery函数的基本语法: $(document).ready(function(){ //代码块: }) 2.window.onload()和$(document).ready()的区分: ...

  5. linux 操作系统下简单的命令行操作

    一: 配置linux 操作系统虚拟主机 首先安装一个虚拟机(百度上面有很多哦) , 我主要使用的是VMware workstation 然后 下载一个centos镜像6..5到7都可以; 然后用VMw ...

  6. PHP curl 携带cookie请求抓取源码,模拟登陆。

    公司需要采集一批手机号码,有指定网站.但是需要登陆后才能看到客户号码,手动点击复制太慢,如此就写了以下模拟登陆采集号码程序,分享给大家参考参考. function request_url_data($ ...

  7. Set的源码分析

    Set的内部实现其实是一个Map.即HashSet的内部实现是一个HashMap,TreeSet的内部实现是一个TreeMap,LinkedHashSet的内部实现是一个LinkedHashMap. ...

  8. Java学习笔记二十四:Java中的Object类

    Java中的Object类 一:什么是Object类: Object类是所有类的父类,相当于所有类的老祖宗,如果一个类没有使用extends关键字明确标识继承另外一个类,那么这个类默认继承Object ...

  9. Fibonacci递归以及数组实现

    说起Fibonacci数列,首先想到的就是递归算法了,这也是帮助理解递归算法比较经典的题目实现如下: public static int Fibonacci(int n){    if (n == 0 ...

  10. 【8086汇编-Day7】关于多个段的程序的实验

    实验一 实验二 实验三 实验四 实验五 实验六 总结 在集成环境下,内存从0770段开始按照段的先后顺序和内容多少分配,并且分配的都是16的倍数 关于实际占用的空间公式的话其实极容易想到(假设有N个字 ...