本題是典型的最大流最小割模型,利用最大流等於最小割求解,將每個城市拆成兩個點,之間連容量為w的邊,注意起點和終點連容量為無窮大的邊,然後為了方便,起點連源,終點連匯,容量也為無窮大,城市之間連容量為無窮大的雙向邊,直接跑最大流即可。
My Code:
#include <cstdio><br />#include <cstring><br />#include <cstdlib><br />#include <algorithm><br />using namespace std;<br />int get()<br />{<br />char ch;<br />int flag = 0, tmp = 0;<br />for (ch = getchar(); ch < 48 || ch > 57; ch = getchar())<br />if (ch == int('-')) break;<br />if (ch == int('-')) flag = 1; else tmp = int(ch) - 48;<br />for (ch = getchar(); 48 <= ch && ch <= 57; ch = getchar())<br />tmp = tmp * 10 + int(ch) - 48;<br />return (flag) ? -tmp : tmp;<br />}<br />const int MAX=210;<br />const int oo=0x3f3f3f3f;<br />struct Edge{<br />int ne,num,cap;<br />}e[2*MAX*MAX];<br />int pre[MAX],pree[MAX],low[MAX],gap[MAX],cur[MAX],dist[MAX];<br />int p[MAX];<br />int n,st,ed,K;<br />void add(const int& u,const int& v,const int& cap){<br />e[K].num=v;e[K].cap=cap;e[K].ne=p[u];p[u]=K++;<br />e[K].num=u;e[K].cap=0;e[K].ne=p[v];p[v]=K++;<br />}<br />int sap(){<br />int ret=0;<br />bool done;<br />memset(dist,0,sizeof(dist));<br />memset(gap,0,sizeof(gap));<br />memset(low,0,sizeof(low));<br />for(int i=0;i<n;i++)cur[i]=p[i];</p><p>int u=st;<br />gap[0]=n;<br />low[st]=oo;<br />while(dist[st]<n){<br />done=true;<br />for(int i=cur[u];~i;i=e[i].ne){<br />int v=e[i].num;<br />cur[u]=i;<br />if(e[i].cap&&dist[u]==dist[v]+1){<br />pre[v]=u;pree[v]=i;<br />low[v]=min(low[u],e[i].cap);<br />u=v;<br />if(u==ed){<br />do{<br />e[pree[u]].cap-=low[ed];<br />e[pree[u]^1].cap+=low[ed];<br />u=pre[u];<br />}while(u!=st);<br />ret+=low[ed];<br />}<br />done=false;<br />break;<br />}<br />}<br />if(done){<br />gap[dist[u]]--;<br />if(!gap[dist[u]])return ret;<br />dist[u]=n;cur[u]=p[u];<br />for(int i=p[u];~i;i=e[i].ne){<br />if(e[i].cap)dist[u]=min(dist[u],dist[e[i].num]+1);<br />}<br />gap[dist[u]]++;<br />if(u!=st)u=pre[u];<br />}<br />}</p><p>return ret;<br />}<br />int main(){<br />int T;<br />int nc,m,u,v,w,s,t;</p><p>T=get();<br />while(T--){<br />nc=get();<br />n=nc*2+2;<br />st=0;<br />ed=n-1;<br />for(int i=0;i<n;i++)p[i]=-1;K=0;<br />m=get();<br />s=get();<br />t=get();<br />add(st,s,oo);<br />add(t+nc,ed,oo);<br />for(int i=1;i<=nc;i++){<br />w=get();<br />if(i!=s&&i!=t)add(i,i+nc,w);<br />else add(i,i+nc,oo);<br />}<br />while(m--){<br />u=get();<br />v=get();<br />add(u+nc,v,oo);<br />add(v+nc,u,oo);<br />}</p><p>printf("%d/n",sap());<br />}</p><p>return 0;<br />}<br />