677-碟战
内存限制:64MB 时间限制:2000ms 特判: No
通过数:2 提交数:2 难度:4
题目描述:
知己知彼,百战不殆!在战争中如果被敌人掌握了自己的机密,失败是必然的。K国在一场战争中屡屡失败,就想到自己的某些城市可能会有敌方的间谍。
在仔细调查后,终于得知在哪些城市存在间谍。当然这个消息也被敌方间谍得知,所以间谍们开始撤离,试图到达K国唯一机场,然后抢夺飞机回国。由于城市内部比较复杂,K国领导人决定封锁道路,阻止所有间谍到达机场。城市编号为1~N,两个城市有不超过1条双向道路相连。机场在N号城市,不会有间碟。
由于要节约兵力,至少要封锁多少条道路才能阻止所有间谍到达机场?
输入描述:
第一行包含一个整数T(T <= 100),为测试数据组数。 接下来每组测试数据第一行包含三个整数n,m,p(2<= n <= 200,1< m < 20000,1 <= p < n),分别表示城市数量,道路数量,存在间谍的城市的数量。 接下来的一行包含p个整数x(1 <= x < n),表示存在间谍城市的编号。 接下来的m行,每行包含两个整数i,j,表示城市i与城市j有道路相通。
输出描述:
输出“Case #i: ans”(不含引号),i为第i组数据,ans为需要封锁道路的条数。
样例输入:
2 4 4 2 1 2 1 2 2 4 1 3 3 4 4 3 2 1 2 2 3 3 4 2 4
样例输出:
Case #1: 2 Case #2: 2
由最大流最小割定理可知我们求出最大流就是答案。建立一个源点S,向所有有间谍的点连边,容量为
inf(因为不确定这个点有几条路能到终点),然后加上题目中给的边,容量是1,然后跑到N点的最大流
就是答案。
所有间谍点都到不了终点<==>从S点出发到不了终点<==>求S-T最大流
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define inf 0x3f3f3f3f 4 int flow[220][220],d[220],N; 5 bool vis[220]; 6 bool bfs(){ 7 queue<int>q; 8 q.push(N); 9 d[N]=0; 10 memset(vis,0,sizeof(vis)); 11 vis[N]=1; 12 while(!q.empty()){ 13 int u=q.front();q.pop(); 14 for(int i=1;i<=N;++i){ 15 if(!vis[i] && flow[u][i]){ 16 vis[i]=1; 17 d[i]=d[u]+1; 18 q.push(i); 19 } 20 } 21 } 22 return vis[N-1]; 23 } 24 int dfs(int u,int a){ 25 if(u==N-1 ||a==0) return a; 26 int f,ans=0; 27 for(int i=1;i<=N;++i){ 28 if(d[i]==d[u]+1 && (f=dfs(i,min(a,flow[u][i])))>0){ 29 flow[u][i]-=f; 30 flow[i][u]+=f; 31 ans+=f; 32 a-=f; 33 if(!a) break; 34 } 35 } 36 return ans; 37 } 38 int solve(){ 39 int ans=0; 40 while(bfs()){ 41 ans+=dfs(N,inf); 42 } 43 return ans; 44 } 45 int main(){ 46 int t,i,j,k,u,v,m,p; 47 cin>>t; 48 for(int cas=1;cas<=t;++cas){ 49 memset(flow,0,sizeof(flow)); 50 cin>>N>>m>>p,++N; 51 for(i=1;i<=p;++i){ 52 scanf("%d",&u); 53 flow[N][u]=inf; 54 } 55 while(m--){ 56 scanf("%d%d",&u,&v); 57 flow[u][v]++; 58 flow[v][u]++; 59 } 60 printf("Case #%d: %d ",cas,solve()); 61 } 62 return 0; 63 }