测试poj 2914 点从0到n-1
#define N 510
int map[N][N];
int sum[N];//记录w(A,i)
int v[N]; //给每个点装个马甲,在删点的时候用
bool visit[N];//标记是否加入了A集合
int solve(int n)
{
int ans=1e9;
REP(i,n) v[i]=i; //最开始每个马甲初始化为自身
while(n>1)
{
memset(visit,0,sizeof(visit));
memset(sum,0,sizeof(sum));
int k,pre=0;
for(int i=1;i<n;i++)
{
k=-1;
for(int j=1;j<n;j++)
if(!visit[v[j]])
{
sum[v[j]]+=map[v[pre]][v[j]];
if(k==-1 || sum[v[k]]<sum[v[j]]) k=j; //选择出最大的w(A,v[j])
}
visit[v[k]]=1;//把v[k]只想的点加入A集合
//在循环的过程中马甲会变化,v[k]不一定是指向k的
if(i==n-1) break;
pre=k;
}
ans=min(ans,sum[v[k]]);
if(ans==0) return 0;
REP(j,n) map[v[j]][v[pre]]=map[v[pre]][v[j]]+=map[v[k]][v[j]];
v[k]=v[--n];
//这就是这道题为什么要用马甲的地方
//你需要删掉的是k点,并且总点数要减一
//所以你就把马甲披在了第n-1个点上,而因为--n了,以后的循环便不会直接循环到第n-1个点
//而是通过v[k]来访问第n-1个点,同时删掉了k点
}
return ans;
}
int main()
{
int n,m,x,y,c;
while(cin>>n>>m)
{
memset(map,0,sizeof(map));
while(m--)
{
scanf("%d%d%d",&x,&y,&c);
map[x][y]+=c;
map[y][x]+=c;
}
cout<<solve(n)<<endl;
}
return 0;
}
模板二
#include<cstdio>
#include<cstring>
#include<climits>
const int N = 501;
int n,mat[N][N],del[N],vis[N],dist[N];
int S,T;
int search(int tn){//T表征最后一个扩展进最大生成树的点,S是倒数第二个
int i,j,tmp,max,cut;
T=S=-1;
memset(vis,0,sizeof(vis));
memset(dist,0,sizeof(dist));//最大生成树
for(i=0;i<=n-tn;i++){
max=-1;
for(j=0;j<n;j++){
if(!vis[j] && !del[j] && dist[j]>max)
max=dist[j], tmp=j;
}
S=T; T=tmp;
cut=max;
vis[T]=1;
for(j=0;j<n;j++){
if(!vis[j] && !del[j])
dist[j]+=mat[T][j];
}
}
return cut;
}
int Stoer_Wagner(){
int ans=INT_MAX;
memset(del,0,sizeof(del));
for(int i=1;i<n;i++){//i 表征搜索次数,i越大图中剩余的点越少,自然搜索次数越少
int cut=search(i);
if(cut<ans)ans=cut;
if(ans==0)return 0;//图不连通时最小割为0
del[T]=1;
for(int j=0;j<n;j++){//S,T合并
if(!del[j])mat[S][j]=mat[j][S]+=mat[T][j];
}
}
return ans;
}
int main()
{
int a,b,c,m;
while(~scanf("%d%d",&n,&m))
{
memset(mat,0,sizeof(mat));
while(m--){
scanf("%d%d%d",&a,&b,&c);
mat[a][b]=mat[b][a]+=c;
}
int ans=Stoer_Wagner();
printf("%d\n",ans);
}
return 0;
}