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最大流
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
int flow[][],d[],N;
bool vis[];
bool bfs(){
queue<int>q;
q.push(N);
d[N]=;
memset(vis,,sizeof(vis));
vis[N]=;
while(!q.empty()){
int u=q.front();q.pop();
for(int i=;i<=N;++i){
if(!vis[i] && flow[u][i]){
vis[i]=;
d[i]=d[u]+;
q.push(i);
}
}
}
return vis[N-];
}
int dfs(int u,int a){
if(u==N- ||a==) return a;
int f,ans=;
for(int i=;i<=N;++i){
if(d[i]==d[u]+ && (f=dfs(i,min(a,flow[u][i])))>){
flow[u][i]-=f;
flow[i][u]+=f;
ans+=f;
a-=f;
if(!a) break;
}
}
return ans;
}
int solve(){
int ans=;
while(bfs()){
ans+=dfs(N,inf);
}
return ans;
}
int main(){
int t,i,j,k,u,v,m,p;
cin>>t;
for(int cas=;cas<=t;++cas){
memset(flow,,sizeof(flow));
cin>>N>>m>>p,++N;
for(i=;i<=p;++i){
scanf("%d",&u);
flow[N][u]=inf;
}
while(m--){
scanf("%d%d",&u,&v);
flow[u][v]++;
flow[v][u]++;
}
printf("Case #%d: %d\n",cas,solve());
}
return ;
}