题目链接在这里:20182019-acmicpc-pacific-northwest-regional-contest-div-1-en.pdf (codeforces.com)
题目大意是给了一个图,要你用最小的代价把小偷封住不让他跑出去,从题意来看是一道很明显的最小割的题目。
对于这种非典型的最小割常见思路是拆点。将每个点拆成入点和出点,入点和出点之间连一条边,如果当前为字母,该边的权值即为字母对应的权值,否则为无穷大(表示此处流量没有限制)。然后每个点的出点和相邻点的入点连一条边,权值为无穷大,表示此处流量没有限制。最后跑网络流最小割。
关于网络流最大流最小割,可以看这个视频学习:
有几个要注意的,一个是建边的时候要同时建两条边,反边的权值为0.另一个是tot的初值要为1,因为这样每个边^1才是它的反边。
1 #include "bits/stdc++.h" 2 #define fi first 3 #define se second 4 using namespace std; 5 const int MAX=1e5+5; 6 const int oo=1e9; 7 char s[35][35]; 8 int n,m,c,a[35],ss,tt; 9 int tot,head[MAX],adj[MAX],wei[MAX],nxt[MAX]; 10 int deep[MAX]; 11 int dx[]={1,0,-1,0}; 12 int dy[]={0,1,0,-1}; 13 void addedge(int u,int v,int w){ 14 tot++; 15 adj[tot]=v; 16 wei[tot]=w; 17 nxt[tot]=head[u]; 18 head[u]=tot; 19 tot++; 20 adj[tot]=u; 21 wei[tot]=0; 22 nxt[tot]=head[v]; 23 head[v]=tot; 24 } 25 inline int getid(int x,int y,int z){ 26 if (x<1 || x>n || y<1 || y>m) return MAX-5; 27 return 2*((x-1)*m+y)+z; 28 } 29 bool bfs(){ 30 int i,j,zt; 31 queue <int> q; 32 while (!q.empty()) q.pop(); 33 q.push(ss); 34 memset(deep,-1,sizeof(deep)); 35 deep[ss]=0; 36 while (!q.empty()){ 37 zt=q.front(); q.pop(); 38 for (i=head[zt];i;i=nxt[i]) 39 if (deep[adj[i]]==-1 && wei[i]>0){ 40 deep[adj[i]]=deep[zt]+1; 41 q.push(adj[i]); 42 } 43 } 44 return (deep[tt]!=-1); 45 } 46 int dfs(int x,int v){ 47 if (x==tt) return v; 48 int i,j,now=0,zt; 49 for (i=head[x];i && now<v;i=nxt[i]) 50 if (deep[adj[i]]==deep[x]+1 && wei[i]>0){ 51 zt=dfs(adj[i],min(wei[i],v-now)); 52 now+=zt; 53 wei[i]-=zt; 54 wei[i^1]+=zt; 55 } 56 if (now==0) deep[x]=-2; 57 return now; 58 } 59 int main(){ 60 freopen ("e.in","r",stdin); 61 freopen ("e.out","w",stdout); 62 int i,j,k,zt,ans=0; 63 scanf("%d%d%d",&m,&n,&c); 64 for (i=1;i<=n;i++) 65 scanf("%s",s[i]+1); 66 for (i=1;i<=c;i++) 67 scanf("%d",a+i); 68 tot=1;tt=MAX-5; 69 memset(head,0,sizeof(head)); 70 for (i=1;i<=n;i++) 71 for (j=1;j<=m;j++){ 72 if (s[i][j]=='B') ss=getid(i,j,1); 73 if (s[i][j]=='.') 74 addedge(getid(i,j,0),getid(i,j,1),oo); 75 if (s[i][j]>='a' && s[i][j]<='z') 76 addedge(getid(i,j,0),getid(i,j,1),a[s[i][j]-'a'+1]); 77 for (k=0;k<4;k++) 78 addedge(getid(i,j,1),getid(i+dx[k],j+dy[k],0),oo); 79 } 80 ans=0; 81 while (bfs()){ 82 while (zt=dfs(ss,oo),zt){ 83 ans+=zt; 84 if (ans>=1e9) goto away; 85 } 86 } 87 away:printf("%d",(ans<1e9?ans:-1)); 88 return 0; 89 }