fzu1844 Earthquake Damage (网络流 最大流最小割/ISAP)

19 篇文章 0 订阅

Time Limit: 1000MS Memory Limit: 32768KB 64bit IO Format: %I64d & %I64u

[]   [Go Back]   [Status]  

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.

Sample Input

5 5 2
1 2
2 3
3 5
2 4
4 5
4
5

Sample Output

1

Hint

Only city 2 being damaged gives such a scenario.


#include <cstdio>
#include <cstring>
#include <algorithm>
const long M=6100;
const long NE=121000;
const long inf=1<<30;

struct ISAP{
    long head[M],next[NE],to[NE],cap[NE],cnt;
    long dist[M],gap[M],pre[M],cur[M],n;

    void init_edge(long x){
        n=x;
        memset(head,-1,sizeof(head));
        cnt=0;
    }
    void add_edge(long u,long v,long c){
        next[cnt]=head[u]; to[cnt]=v; cap[cnt]=c; head[u]=cnt++;
        next[cnt]=head[v]; to[cnt]=u; cap[cnt]=0; head[v]=cnt++;
    }

    long MaxFlow(long s,long t){
        long maxflow=0,flow=inf,flag;
        long u,v;
        for (long i=0;i<=n;++i){
            dist[i]=gap[i]=0;
            cur[i]=head[i];
        }
        u=pre[s]=s; gap[0]=n;

        while (dist[s]<n){
            flag=0;
            for (long &i=cur[u];i!=-1;i=next[i]){
                v=to[i];
                if (cap[i]>0 && dist[u]==dist[v]+1){
                    flow=std::min(flow,cap[i]);
                    pre[v]=u;
                    u=v;
                    flag=1; 
                    if (v==t){
                        maxflow+=flow;
                        while (u!=s){
                            u=pre[u];
                            cap[cur[u]]-=flow;
                            cap[cur[u]^1]+=flow;
                        }
                        flow=inf;
                    }
                    break;
                }
            }

            if (flag) continue;

            long min_dist=n;
            for (long i=head[u];i!=-1;i=next[i]){
                v=to[i];
                if (cap[i]>0 && dist[v]<min_dist){
                    min_dist=dist[v];
                    cur[u]=i;
                }
            }

            if ((--gap[dist[u]])==0) break;
            gap[dist[u]=min_dist+1]++;
            u=pre[u];
        }
        return maxflow;
    }
}G;

int main(){
    long p,c,n,vis[M];
    while (~scanf("%d%d%d",&p,&c,&n)){
		long s=1,t=2*p+1;
        G.init_edge(t);
        memset(vis,0,sizeof(vis));
        while (c--){
            long u,v;
            scanf("%d%d",&u,&v);
            G.add_edge(u+p,v,inf);
            G.add_edge(v+p,u,inf);
        }
        while (n--){
            long x;
            scanf("%d",&x);
            vis[x]=1;
            G.add_edge(x,t,inf);
        }

		G.add_edge(1,1+p,inf);
        for (long i=2;i<=p;++i)
            if (!vis[i]) G.add_edge(i,i+p,1);
            else G.add_edge(i,i+p,inf);

        printf("%d\n",G.MaxFlow(s,t));
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值