题目:恐怖分子
题目描述
一个国家由n个城市组成,任意两个城市间都有一条双向的道路。如今,恐怖分子想要炸掉其中的一些道路,使得这n个城市变得不再连通,也就是说,存在至少两个城市,它们之间不可通过道路互相到达。要炸毁一条道路需要一定的代价。请你计算一下要使恐怖分子达到它们的目的,所需要的最小总代价是多少。
结果说明:破坏道路(1,3),(1,4),(2,3),(2,4)可以使城市1,2与城市3,4之间无法到达,所需的最小总代价为4。
输入格式
第一行为正整数n (n ≤ 50),表示城市的个数,接下来的n行每行由n个0~9之间的数字组成,数字之间没有空格或任何其他字符间隔,第i行的第j个数字表示要破坏城市i与城市j之间的道路所需要的代价。输入数据保证对于任意i, j。第i行的第j个数字与第j行的第i个数相等,且对于所有的i,第i行的第i个数字都等于0。
输出格式
输出仅有一个整数,即要破坏这n个城市的连通性,所需要的最小总代价。
最大流最小割定理。sap算法。
#include<iostream> #include<string.h> //#include<fstream> #define Max 51 #define MaxInt 0xfffffff using namespace std; //ifstream fin("cin.in"); int n,t; int g[Max][Max],f[Max][Max],d[Max],num[Max]; int ans=MaxInt; int flow,mimi; bool found; void aug(int u){//cout<<u<<endl; if(u==t) { flow+=mimi; found=1; return ; } int cord=mimi; int mind=n-1; int v; for(v=1;v<=n;++v) { if(f[u][v]) { if(d[u]==d[v]+1) { mimi=min(mimi,f[u][v]); aug(v); if(d[1]>=n) return; if(found) break; mimi=cord; } mind=min(mind,d[v]); } } if(found) {f[u][v]-=mimi;f[v][u]+=mimi;} else { num[d[u]]--; if(num[d[u]]==0) d[1]=n; d[u]=mind+1; num[d[u]]++; } } int asp(){ memset(d,0,sizeof(d)); memset(num,0,sizeof(num)); memcpy(f,g,sizeof(g)); num[0]=n; flow=0; while(d[1]<n) { found=0; mimi=MaxInt; aug(1); } return flow; } int main() { cin>>n; string s; for(int i=1;i<=n;++i) { cin>>s; for(int j=0;j<n;++j) g[i][j+1]=s[j]-'0'; } for(int i=2;i<=n;++i) { t=i; ans=min(ans,asp()); //cout<<ans<<endl; } cout<<ans<<endl; //system("pause"); }