FZU 1844 Earthquake Damage(最大流最小割)
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(最大流最小割)的更多相关文章
- bzoj 1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害
1585: [Usaco2009 Mar]Earthquake Damage 2 地震伤害 Description Farmer John的农场里有P个牧场,有C条无向道路连接着他们,第i条道路连接着 ...
- hiho 第116周,最大流最小割定理,求最小割集S,T
小Hi:在上一周的Hiho一下中我们初步讲解了网络流的概念以及常规解法,小Ho你还记得内容么? 小Ho:我记得!网络流就是给定了一张图G=(V,E),以及源点s和汇点t.每一条边e(u,v)具有容量c ...
- hihocoder 网络流二·最大流最小割定理
网络流二·最大流最小割定理 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi:在上一周的Hiho一下中我们初步讲解了网络流的概念以及常规解法,小Ho你还记得内容么? ...
- [HihoCoder1378]网络流二·最大流最小割定理
思路: 根据最大流最小割定理可得最大流与最小割相等,所以可以先跑一遍EdmondsKarp算法.接下来要求的是经过最小割切割后的图中$S$所属的点集.本来的思路是用并查集处理所有前向边构成的残量网络, ...
- HDU 1569 方格取数(2)(最大流最小割の最大权独立集)
Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大. ...
- 【codevs1907】方格取数3(最大流最小割定理)
网址:http://codevs.cn/problem/1907/ 题意:在一个矩阵里选不相邻的若干个数,使这些数的和最大. 我们可以把它看成一个最小割,答案就是矩阵中的所有数-最小割.先把矩阵按国际 ...
- 洛谷 P2932 [USACO09JAN]地震造成的破坏Earthquake Damage
P2932 [USACO09JAN]地震造成的破坏Earthquake Damage 题目描述 Wisconsin has had an earthquake that has struck Farm ...
- 紫书 例题 11-12 UVa 1515 (最大流最小割)
这道题要分隔草和洞, 然后刘汝佳就想到了"割"(不知道他怎么想的, 反正我没想到) 然后就按照这个思路走, 网络流建模然后求最大流最小割. 分成两部分, S和草连, 洞和T连 外围 ...
- HDU-4289-Control(最大流最小割,拆点)
链接: https://vjudge.net/problem/HDU-4289 题意: You, the head of Department of Security, recently receiv ...
随机推荐
- HDU1398 Square Coins(生成函数)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...
- linux中删除文件内空白行的几种方法。
linux中删除文件内空白行的几种方法 有时你可能需要在 Linux 中删除某个文件中的空行.如果是的,你可以使用下面方法中的其中一个.有很多方法可以做到,但我在这里只是列举一些简单的方法. 你可能已 ...
- 利用CSS3选择器实现表格的斑马纹
要用到的Css3选择器 element:nth-child(number){ } 选择器匹配属于其父元素的第 number 个子元素 参数 Number odd 奇数 even 偶数 W3School ...
- 7. CSS装饰网页的样式
CSS中有哪些用来装饰网页的样式呢?在这里我们对一些常用的样式做了总结. 字体样式 /* * 一般样式书写 */ .font_style_1{ font-family: "华文行楷" ...
- CAT 安装运行配置教程
CAT安装教程 首先安装mysql数据库,具体步骤参阅<mysql免安装教程>--http://www.cnblogs.com/halberts/p/8723938.html 下载CAT代 ...
- linux使用logrotate工具管理日志轮替
对于Linux系统安全来说,日志文件是极其重要的工具.logrotate程序是一个日志文件管理工具.用于分割日志文件,删除旧的日志文件,并创建新的日志文件,起到"转储"作用.可以节 ...
- 让pandas的输出结果中显示全部数据
import pandas as pd pd.set_option('display.max_columns', 1000) pd.set_option('display.width', 1000) ...
- 浅谈fail-fast机制
fail-fast机制即为快速失败机制,个人认为是一种防护措施,在集合结构发生改变的时候,使尽全力抛出ConcurrentModificationException,所以该机制大部分用途都是用来检测B ...
- Touch table
On this page I present the results of my touch action research. I concentrated on the few basic acti ...
- 全球订单最多的成都优步推出"南北通勤线"业务
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...