首页 写随笔

cdcq(本博客废弃!现用博客:https://www.cnblogs.com/cdcq/)

本博客废弃!现用博客:https://www.cnblogs.com/cdcq/

导航

传纸条

这个建图也是很妙

原题:
小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个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 }
View Code

 

posted on 2017-01-18 17:06  cdcq_old  阅读(201)  评论(0编辑  收藏  举报