这个建图也是很妙
原题:
小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n)。从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。
在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。
还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用0表示),可以用一个0-100的自然数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度只和最大。现在,请你帮助小渊和小轩找到这样的两条路径。
1<=m,n<=50
明明两个dfs就可以A掉的题非要用费用流写系列
用费用流的话建图是个很大的问题,我考虑过建两个图或者跑两边,酱紫就不能满足只能经过一次的限制了,又想过把源和汇连起来,酱紫就不能限制去的时候和回来的时候走的方向限制了
然后看了山神的题解,只能说妙啊
为啥非要跑回来呢,题目本质是求两条不相交的路,在建图的时候给源和汇连的边流量为2不就行了
网络流妙啊
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 int read(){int z=0,mark=1; char ch=getchar(); 8 while(ch<'0'||ch>'9'){if(ch=='-')mark=-1; ch=getchar();} 9 while(ch>='0'&&ch<='9'){z=(z<<3)+(z<<1)+ch-'0'; ch=getchar();} 10 return z*mark; 11 } 12 const int oo=168430090; 13 struct ddd{int next,y,evalue,rev,cost;}e[1100000]; int LINK[510000],ltop=0; 14 inline void insert(int x,int y,int z,int _cost){ 15 e[++ltop].next=LINK[x];LINK[x]=ltop;e[ltop].y=y;e[ltop].evalue=z;e[ltop].rev=ltop+1;e[ltop].cost=_cost; 16 e[++ltop].next=LINK[y];LINK[y]=ltop;e[ltop].y=x;e[ltop].evalue=0;e[ltop].rev=ltop-1;e[ltop].cost=-_cost; 17 } 18 int n,m,a[110][110]; int s,t; int S; 19 int QUEUE[510000],head=0; bool visited[510000]; 20 int last[510000],last_e[510000]; 21 int dist[510000]; 22 inline int get_id(int x,int y){return (x-1)*n+y-1;} 23 bool spfa(){ 24 memset(visited,0,sizeof(visited)); 25 memset(dist,-1,sizeof(dist)); 26 QUEUE[head=1]=s; visited[s]=true; dist[s]=0; 27 for(int k=1;k<=head;k++){ 28 for(int i=LINK[QUEUE[k]];i;i=e[i].next) 29 if(e[i].evalue && dist[QUEUE[k]]+e[i].cost>dist[e[i].y]){ 30 dist[e[i].y]=dist[QUEUE[k]]+e[i].cost; 31 last[e[i].y]=QUEUE[k],last_e[e[i].y]=i; 32 if(!visited[e[i].y]){ QUEUE[++head]=e[i].y; visited[e[i].y]=true;} 33 } 34 visited[QUEUE[k]]=false; 35 } 36 return dist[t]!=-1; 37 } 38 int cost_flow(){ 39 int bowl=0; 40 while(spfa()){ 41 int min_flow=oo; 42 for(int i=t;i!=s;i=last[i]) min_flow=min(min_flow,e[last_e[i]].evalue); 43 for(int i=t;i!=s;i=last[i]){ 44 bowl+=e[last_e[i]].cost; 45 e[last_e[i]].evalue-=min_flow,e[e[last_e[i]].rev].evalue+=min_flow; 46 } 47 } 48 return bowl; 49 } 50 int main(){//freopen("ddd.in","r",stdin); 51 cin>>m>>n; s=0,S=m*n; t=S*2+1; 52 for(int i=1;i<=m;i++)for(int j=1;j<=n;j++)a[i][j]=read(); 53 for(int i=1;i<=m;i++)for(int j=1;j<=n;j++){ 54 int _id=get_id(i,j); 55 if((i==1 && j==1)||(i==m && j==n)) insert(_id,_id+S,2,0); 56 else insert(_id,_id+S,1,a[i][j]); 57 if(j!=n) insert(_id+S,get_id(i,j+1),oo,0); 58 if(i!=m) insert(_id+S,get_id(i+1,j),oo,0); 59 } 60 insert(s,get_id(1,1),2,0),insert(get_id(m,n)+S,t,2,0); 61 cout<<cost_flow()<<endl; 62 return 0; 63 }