您的位置:首页 > 其它

vijos 1524 最小监视代价 SAP

2010-07-22 23:20 218 查看
背景 Background

看到Vijos上此类型的题目较少,特地放一道上来给大家练练。

描述 Description

由于yxy小朋友做了一些不该做的事,他被jzp关进了一个迷宫里。由于jzp最近比较忙,疏忽大意了一些,yxy可以在迷宫中任意走动。整个迷宫可以被看作是一个无向图。迷宫中有一些结点有传送点,可以让他逃离这个迷宫。jzp发明了一种机器人,可以监视迷宫中的道路,被监视的道路yxy不能通过,我们简单的认为监视一条道路的代价即为这条道路的长度。现在jzp正在忙,请你编一个程序算出使yxy无法逃离迷宫的最小监控总代价。(yxy一开始在1号结点)

输入格式 Input Format

第1行:两个自然数n和e,分别表示迷宫的节点数和边数。

第2至e+1行:每行三个自然数a、b和w,表示a和b之间有一条道路,长度为w。

第e+2行:一个自然数m,表示有传送点结点的个数。

第e+3行:m个自然数,表示有传送点的结点。

输出格式 Output Format

一个自然数,表示最小监视总代价。

样例输入 Sample Input

5 5

1 2 1

1 3 2

2 5 3

2 3 3

3 4 2

2

4 5

样例输出 Sample Output

3

时间限制 Time Limitation

每个测试点1s

注释 Hint

n<100,e<300,m<n

1<=a,b<=n

w<=maxint

来源 Source

经典问题改编

//通过求最小割来求最大流

#include<iostream>

#include<cstdio>

#include<cstring>

using namespace std;

const int inf=(1<<31)-1;

const int point_num=300;

int cap[point_num][point_num],dist[point_num],gap[point_num];//初始化见main里面

int s0,t0,n;//源,汇和点数

int find_path(int p,int limit=0x3f3f3f3f)

{

if(p==t0) return limit;

for(int i=0;i<n;i++)

if(dist[p]==dist[i]+1 && cap[p][i]>0)

{

int t=find_path(i,min(cap[p][i],limit));

if(t<0) return t;

if(t>0)

{

cap[p][i]-=t;

cap[i][p]+=t;

return t;

}

}

int label=n;

for(int i=0;i<n;i++) if(cap[p][i]>0) label=min(label,dist[i]+1);

if(--gap[dist[p]]==0 || dist[s0]>=n ) return -1;

++gap[dist[p]=label];

return 0;

}

int sap()

{

//初始化s,t

s0=0,t0=n-1;

int t=0,maxflow=0;

gap[s0]=n;

while((t=find_path(s0))>=0) maxflow+=t;

return maxflow;

}

int main()

{

int m;

while(cin>>n>>m)

{

//初始化

memset(cap,0,sizeof(cap));

memset(dist,0,sizeof(dist));

memset(gap,0,sizeof(gap));

//初始化cap

for(int i=1;i<=m;i++)

{

int x,y,c;

scanf("%d%d%d",&x,&y,&c);

cap[x-1][y-1]+=c;

cap[y-1][x-1]+=c;

}

int ci;cin>>ci;

while(ci--)

{

int x;

scanf("%d",&x);

cap[x-1]
=inf;

}

n++;//增加汇

int ans=sap();

cout<<ans<<endl;

}

return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: