[Luogu] 洛谷 P4013 题解【数字梯形问题】

感动,终于过了(由此我发现了自己是有多么的菜……)

其实其他几个发题解大佬都已经把思路讲的很清楚了,我就不细讲了,主要是提醒大家一下

可能这一题的提交记录中也只有我交了这么多次,发了三篇讨论,连着改了一个星期吧……

大致的思路:

    • 第一问要保证路径互不相交,也就是不能让一个点被经过多次

    • 是不是感觉很熟悉!是不是!没错,就是拆点大法!用拆点来保证只经过这个点一次即可QQwQ

    • 第二问仅不允许在路径上相交,就没必要拆点啦QQwQ

    • 同样的,用流量为1来保证路径只经过一次

    • 第三问一看……噢,这不相当于是没有限制么QQQQQwQ!

    • 激动的我们将流量开大并什么也不想管

以下是我主要出问题的几个点(求不要嘲讽):

  • memset赋负数时只能赋-1,赋其他的数会变成奇怪的负数,所以在判断时要看他是否<0,否则就会出错……

  • 这一题不要看范围只有20就不开大数组范围,一定要开大!!,不然就会出现奇怪的错误,因为数组是连续的,所以一旦爆数组就会修改到其他几个数组然后就挂了……(像我就T到飞起……)

    扫描二维码关注公众号,回复: 4513133 查看本文章

之前我改代码是发现……题解中没有一篇Dinic递归的代码!

于是给大家一个并手动普度众生

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 inline int read()
  4 {
  5     int f=1,w=0;char x=0;
  6     while(x<'0'||x>'9') {if(x=='-') f=-1; x=getchar();}
  7     while(x!=EOF&&x>='0'&&x<='9') {w=(w<<3)+(w<<1)+(x^48);x=getchar();}
  8     return f*w;
  9 }
 10 int head[200020],cur[200020],num_edge=-1;
 11 int a[1001][1001],b[1001][1001],cnt;
 12 int n,m,s,t,ans;
 13 struct Edge
 14 {
 15     int next,to,dis,cos;
 16 }edge[200020];
 17 inline void add(int from,int to,int dis,int cos)
 18 {
 19     edge[++num_edge].next=head[from];
 20     edge[num_edge].to=to;
 21     edge[num_edge].dis=dis;
 22     edge[num_edge].cos=cos;
 23     head[from]=num_edge;
 24 }
 25 inline void clear()
 26 {
 27     num_edge=-1;
 28     memset(head,-1,sizeof(head));
 29     ans=0;
 30 }
 31 int d[200000],v[200000],flo[200000];
 32 inline bool bfs()
 33 {
 34     memset(d,-50,sizeof(d));
 35     memset(v,0,sizeof(v));
 36     memset(flo,0,sizeof(flo));
 37     queue<int> q;
 38     q.push(s);
 39     d[s]=0;
 40     v[s]=1;flo[s]=1;
 41     while(!q.empty())
 42     {
 43         int x=q.front();
 44         q.pop();
 45         v[x]=0;
 46         for(int i=head[x];i!=-1;i=edge[i].next)
 47         {
 48             int y=edge[i].to;
 49             if(edge[i].dis>0&&d[y]<d[x]+edge[i].cos)
 50             {
 51                 d[y]=d[x]+edge[i].cos;
 52                 flo[y]=flo[x]+1;
 53                 if(!v[y]) { q.push(y); v[y]=1; }
 54             }
 55         }
 56     }
 57     if(d[t]<0) return 0;
 58     else return 1;
 59 }
 60 int dfs(int pos,int dis)
 61 {
 62     if(pos==t) return dis;
 63     for(int i=cur[pos];i!=-1;i=edge[i].next)
 64         if(flo[edge[i].to]==flo[pos]+1&&edge[i].dis!=0&&d[edge[i].to]==d[pos]+edge[i].cos)
 65         {
 66             int data=dfs(edge[i].to,min(dis,edge[i].dis));
 67             if(data>0)
 68             {
 69                 edge[i].dis-=data;
 70                 edge[i^1].dis+=data;
 71                 ans+=edge[i].cos;
 72                 cur[pos]=i;
 73                 return data; 
 74             }
 75         }
 76     return 0;
 77 }
 78 void  Dinic()
 79 {
 80     while(bfs())
 81     {
 82         memcpy(cur,head,sizeof(head));
 83         while(dfs(s,0x3f3f3f3f));
 84     }
 85 }
 86 int main(){
 87     memset(head,-1,sizeof(head));
 88     m=read();
 89     n=read();
 90     for(int i=1;i<=n;i++)
 91         for(int j=1;j<=m+i-1;j++)
 92             a[i][j]=read(),b[i][j]=++cnt;
 93     s=0;
 94     t=cnt*2+3;
 95     for(int i=1;i<=m;i++)
 96         add(s,b[1][i],1,0),add(b[1][i],s,0,0);
 97     for(int i=1;i<n;i++)
 98         for(int j=1;j<=m+i-1;j++)
 99         {
100             add(b[i][j],b[i][j]+cnt,1,a[i][j]);
101             add(b[i][j]+cnt,b[i][j],0,-a[i][j]);
102             add(b[i][j]+cnt,b[i+1][j],1,0);
103             add(b[i+1][j],b[i][j]+cnt,0,0);
104             add(b[i][j]+cnt,b[i+1][j+1],1,0);
105             add(b[i+1][j+1],b[i][j]+cnt,0,0);
106         }
107     for(int i=1;i<=m+n-1;i++)
108     {
109         add(b[n][i],b[n][i]+cnt,1,a[n][i]);
110         add(b[n][i]+cnt,b[n][i],0,-a[n][i]);
111         add(b[n][i]+cnt,t,1,0);
112         add(t,b[n][i]+cnt,0,0);
113     }
114     Dinic();
115     printf("%d\n",ans);
116     clear();
117     for(int i=1;i<=m;i++)
118         add(s,b[1][i],1,0),add(b[1][i],s,0,0);
119     for(int i=1;i<n;i++)
120         for(int j=1;j<=m+i-1;j++)
121         {
122             add(b[i][j],b[i+1][j],1,a[i][j]);
123             add(b[i+1][j],b[i][j],0,-a[i][j]);
124             add(b[i][j],b[i+1][j+1],1,a[i][j]);
125             add(b[i+1][j+1],b[i][j],0,-a[i][j]);
126         }
127     for(int i=1;i<=m+n-1;i++)
128     {
129         add(b[n][i],t,0x3f3f3f3f,a[n][i]);
130         add(t,b[n][i],0,-a[n][i]);
131     }
132     Dinic();
133     printf("%d\n",ans);
134     clear();
135     for(int i=1;i<=m;i++)
136         add(s,b[1][i],1,0),add(b[1][i],s,0,0);
137     for(int i=1;i<n;i++)
138         for(int j=1;j<=m+i-1;j++)
139         {
140             add(b[i][j],b[i+1][j],0x3f3f3f3f,a[i][j]);
141             add(b[i+1][j],b[i][j],0,-a[i][j]);
142             add(b[i][j],b[i+1][j+1],0x3f3f3f3f,a[i][j]);
143             add(b[i+1][j+1],b[i][j],0,-a[i][j]);
144         }
145     for(int i=1;i<=m+n-1;i++)
146     {
147         add(b[n][i],t,0x3f3f3f3f,a[n][i]);
148         add(t,b[n][i],0,-a[n][i]);
149     }
150     Dinic();
151     printf("%d\n",ans);
152 }

猜你喜欢

转载自www.cnblogs.com/wo-shi-zhen-de-cai/p/10122579.html