zoukankan      html  css  js  c++  java
  • 网络流进阶

    study from:

    一篇很好的文章 拆点 拆边

    https://www.cnblogs.com/tweetuzki/p/10422496.html

    认真看解释,造一个简单、有代表性的图,画图辅助理解

    Thieves

    http://acm.hdu.edu.cn/showproblem.php?pid=3491

    最小割=最大流

    拆点(点有流量限制)

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <string>
      5 #include <cmath>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 
     11 const int maxn=1e4+10;
     12 const int inf=1e9;
     13 
     14 struct node
     15 {
     16     int d,len;
     17     node *to,*opp;
     18 }*e[maxn];
     19 
     20 int s,t,q[maxn],dep[maxn];
     21 
     22 void addedge(int x,int y,int z)
     23 {
     24     node *p1,*p2;
     25     p1=new node();
     26     p2=new node();
     27 
     28     p1->d=y;
     29     p1->len=z;
     30     p1->opp=p2;
     31     p1->to=e[x];
     32     e[x]=p1;
     33 
     34     p2->d=x;
     35     p2->len=0;
     36     p2->opp=p1;
     37     p2->to=e[y];
     38     e[y]=p2;
     39 }
     40 
     41 bool bfs()
     42 {
     43     node *p;
     44     int head=0,tail=1,d,dd;
     45     memset(dep,0,sizeof(dep));
     46     dep[s]=1;
     47     q[1]=s;
     48     while (head<tail)
     49     {
     50         head++;
     51         d=q[head];
     52         p=e[d];
     53         while (p)
     54         {
     55             dd=p->d;
     56             if (!dep[dd] && p->len)
     57             {
     58                 q[++tail]=dd;
     59                 dep[dd]=dep[d]+1;
     60             }
     61             p=p->to;
     62         }
     63     }
     64     if (dep[t])
     65         return 1;
     66     return 0;
     67 }
     68 
     69 int dfs(int d,int add)
     70 {
     71     if (!add || d==t)
     72         return add;
     73     int totr=0,r,dd;
     74     node *p=e[d];
     75     while (p)
     76     {
     77         dd=p->d;
     78         if (dep[dd]==dep[d]+1 && (r=dfs(dd,min(add,p->len)))>0)
     79         {
     80             totr+=r;
     81             add-=r;
     82             p->len-=r;
     83             p->opp->len+=r;
     84         }
     85         p=p->to;
     86     }
     87     return totr;
     88 }
     89 
     90 int main()
     91 {
     92     int T,n,m,x,y,i,v,sum;
     93     scanf("%d",&T);
     94     while (T--)
     95     {
     96         scanf("%d%d%d%d",&n,&m,&s,&t);
     97         s+=n;
     98 //        t+=n;
     99         for (i=1;i<=2*n;i++)
    100             e[i]=0;
    101         for (i=1;i<=n;i++)
    102         {
    103             scanf("%d",&v);
    104             addedge(i,i+n,v);
    105         }
    106         while (m--)
    107         {
    108             scanf("%d%d",&x,&y);
    109             addedge(x+n,y,inf);
    110             addedge(y+n,x,inf);
    111         }
    112         sum=0;
    113         while (bfs())
    114             sum+=dfs(s,inf);
    115         printf("%d
    ",sum);
    116     }
    117     return 0;
    118 }

    类似的题目

    Dining

    http://poj.org/problem?id=3281

    https://nanti.jisuanke.com/t/A1106

    菜鸟物流的运输网络

    way1

    拆点,点i连点i+n,流量为1,从原点i入的边连接i+n,从原点i出的边连接点i。

    源点mid,超级汇点连接s,t。

    need边取反,即只适用于双向边

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <string>
      5 #include <cmath>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 #include <queue>
     11 const int maxn=2e2+10;///*2
     12 const int inf=1e9;
     13 #include <assert.h>
     14 
     15 struct node
     16 {
     17     int d,len,cond;
     18     node *to,*opp;
     19 }*e[maxn];
     20 
     21 int n,ss,tt,mid,q[maxn],dep[maxn];
     22 
     23 void addedge(int x,int y,int z)
     24 {
     25     node *p1,*p2;
     26     p1=new node();
     27     p2=new node();
     28 
     29     p1->d=y;
     30     p1->len=z;
     31     p1->opp=p2;
     32     p1->to=e[x];
     33     e[x]=p1;
     34     p1->cond=0;
     35 
     36     p2->d=x;
     37     p2->len=0;
     38     p2->opp=p1;
     39     p2->to=e[y];
     40     e[y]=p2;
     41     p2->cond=1;
     42 }
     43 
     44 bool bfs()
     45 {
     46     node *p;
     47     int head=0,tail=1,d,dd;
     48     memset(dep,0,sizeof(dep));
     49     dep[ss]=1;
     50     q[1]=ss;
     51     while (head<tail)
     52     {
     53         head++;
     54         d=q[head];
     55         p=e[d];
     56         while (p)
     57         {
     58             dd=p->d;
     59             if (!dep[dd] && p->len)
     60             {
     61                 q[++tail]=dd;
     62                 dep[dd]=dep[d]+1;
     63             }
     64             p=p->to;
     65         }
     66     }
     67     if (dep[tt])
     68         return 1;
     69     return 0;
     70 }
     71 
     72 int dfs(int d,int add)
     73 {
     74 //    printf("%d %d
    ",d,add);
     75     if (!add || d==tt)
     76         return add;
     77     int totr=0,r,dd;
     78     node *p=e[d];
     79     while (p)
     80     {
     81         dd=p->d;
     82         if (dep[dd]==dep[d]+1 && (r=dfs(dd,min(add,p->len)))>0)
     83         {
     84             totr+=r;
     85             add-=r;
     86             p->len-=r;
     87             p->opp->len+=r;
     88         }
     89         p=p->to;
     90     }
     91     return totr;
     92 }
     93 
     94 void print(int x)
     95 {
     96     node *p=e[x];
     97     while (p)
     98     {
     99         if (p->cond && p->len)
    100         {
    101             x=p->d;
    102             if (x!=mid)
    103                 print(x);
    104             break;
    105         }
    106         p=p->to;
    107     }
    108     if (x<=n)
    109         printf("%d ",x);
    110 }
    111 
    112 int main()
    113 {
    114     node *p;
    115     int T,m,x,y,i,s,t,sum;
    116     scanf("%d",&T);
    117     while (T--)
    118     {
    119         scanf("%d%d",&n,&m);
    120         scanf("%d%d%d",&s,&t,&mid);
    121         ss=2*n+1;
    122         tt=2*n+2;
    123         for (i=1;i<=2*n+2;i++)
    124             e[i]=0;
    125         for (i=1;i<=n;i++)
    126             if (i==mid)
    127                 addedge(i,i+n,2);
    128             else
    129                 addedge(i,i+n,1);
    130         addedge(2*n+1,mid,2);
    131         addedge(s+n,2*n+2,1);
    132         addedge(t+n,2*n+2,1);
    133         while (m--)
    134         {
    135             scanf("%d%d",&x,&y);
    136             addedge(x+n,y,1);
    137             addedge(y+n,x,1);
    138         }
    139 
    140         sum=0;
    141         while (bfs())
    142             sum+=dfs(ss,inf);
    143 
    144         x=s;
    145         while (x!=mid)
    146         {
    147             if (x<=n)
    148                 printf("%d ",x);
    149             p=e[x];
    150             while (p)
    151             {
    152                 if (p->cond && p->len)
    153                 {
    154                     x=p->d;
    155                     break;
    156                 }
    157                 p=p->to;
    158             }
    159         }
    160         print(t);
    161         printf("%d
    ",t);
    162     }
    163     return 0;
    164 }
    165 /*
    166 4
    167 
    168 5 5
    169 1 5 3
    170 1 2
    171 2 3
    172 3 4
    173 4 5
    174 5 1
    175 
    176 5 5
    177 1 3 5
    178 1 2
    179 2 3
    180 3 4
    181 4 5
    182 5 1
    183 
    184 3 3
    185 1 2 3
    186 2 1
    187 2 3
    188 3 1
    189 
    190 4 6
    191 2 1 4
    192 1 2
    193 1 3
    194 1 4
    195 2 3
    196 2 4
    197 3 4
    198 
    199 10 10
    200 5 3 10
    201 1 2
    202 2 3
    203 3 4
    204 4 5
    205 5 6
    206 6 7
    207 7 8
    208 8 9
    209 9 10
    210 10 1
    211 
    212 3 0
    213 1 2 3
    214 */

    若求最短路径,用费用流。

    但仍需要拆点,见以下情况。

    同样的,不拆点求网络流,采用去环的方式也是不行的,见以下情况。

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <string>
      5 #include <cmath>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 #include <queue>
     11 const int maxn=2e2+10;///*2
     12 const int inf=1e9;
     13 #include <assert.h>
     14 
     15 /*
     16 时间复杂度为O(N*E*k),其中K为最大流值。但时间上的期望时间复杂度为:O(A*E*K),其中A为所有顶点进队列的平均次数,可以证明A一般小于等于2。
     17 */
     18 
     19 struct node
     20 {
     21     int d,len,cost,cond;
     22     node *to,*opp;
     23 }*e[maxn],*pre[maxn];
     24 
     25 int ss,tt,dist[maxn],add[maxn],flow,fee;
     26 bool vis[maxn];
     27 int ans_p,pr[maxn];
     28 
     29 queue<int>st;
     30 
     31 void addedge(int x,int y,int len,int cost)
     32 {
     33     node *p1,*p2;
     34     p1=new node();
     35     p2=new node();
     36 
     37     p1->d=y;
     38     p1->len=len;
     39     p1->cost=cost;
     40     p1->opp=p2;
     41     p1->to=e[x];
     42     p1->cond=0;
     43     e[x]=p1;
     44 
     45     p2->d=x;
     46     p2->len=0;
     47     p2->cost=-cost;
     48     p2->opp=p1;
     49     p2->to=e[y];
     50     p2->cond=1;
     51     e[y]=p2;
     52 }
     53 
     54 void bfs()
     55 {
     56     node *p;
     57     int d,dd;
     58     while (1)
     59     {
     60         memset(dist,0x7f,sizeof(dist));
     61         dist[ss]=0;
     62         add[ss]=inf;
     63         add[tt]=0;
     64 
     65         st.push(ss);
     66         while (!st.empty())
     67         {
     68             d=st.front();
     69             st.pop();
     70             p=e[d];
     71             while (p)
     72             {
     73                 dd=p->d;
     74                 if (p->len && dist[dd]>dist[d]+p->cost)
     75                 {
     76                     dist[dd]=dist[d]+p->cost;
     77                     add[dd]=min(add[d],p->len);
     78                     pre[dd]=p->opp;
     79                     if (!vis[dd])
     80                     {
     81                         vis[dd]=1;
     82                         st.push(dd);
     83                     }
     84                 }
     85                 p=p->to;
     86             }
     87             vis[d]=0;
     88         }
     89 
     90         if (add[tt]==0)
     91             break;
     92 
     93         flow+=add[tt];
     94         fee+=add[tt]*dist[tt];
     95         d=tt;
     96         while (d!=ss)
     97         {
     98             pre[d]->len+=add[tt];
     99             pre[d]->opp->len-=add[tt];
    100             d=pre[d]->d;
    101         }
    102     }
    103 }
    104 
    105 int main()
    106 {
    107     node *p;
    108     int T,n,m,x,y,i,mid,s,t;
    109     scanf("%d",&T);
    110     while (T--)
    111     {
    112         scanf("%d%d",&n,&m);
    113         scanf("%d%d%d",&s,&t,&mid);
    114         ss=2*n+1;
    115         tt=2*n+2;
    116         for (i=1;i<=2*n+2;i++)
    117             e[i]=0;
    118         for (i=1;i<=n;i++)
    119             if (i==mid)
    120                 addedge(i,i+n,2,1);
    121             else
    122                 addedge(i,i+n,1,1);
    123         addedge(2*n+1,mid,2,1);
    124         addedge(s+n,2*n+2,1,1);
    125         addedge(t+n,2*n+2,1,1);
    126         while (m--)
    127         {
    128             scanf("%d%d",&x,&y);
    129             addedge(x+n,y,1,1);
    130             addedge(y+n,x,1,1);
    131         }
    132 
    133         flow=0,fee=0;
    134         bfs();
    135 
    136 //        printf("data=%d %d %d
    ",s,t,mid);
    137 
    138         if (flow!=2)
    139         {
    140             printf("-1
    ");
    141             continue;
    142         }
    143 
    144         ans_p=0;
    145         x=s;
    146         while (x!=mid)
    147         {
    148             if (x<=n)
    149                 pr[++ans_p]=x;
    150             p=e[x];
    151             while (p)
    152             {
    153                 if (p->cond && p->len)
    154                 {
    155                     x=p->d;
    156                     break;
    157                 }
    158                 p=p->to;
    159             }
    160         }
    161         for (i=1;i<=ans_p;i++)
    162             printf("%d ",pr[i]);
    163 
    164         ans_p=0;
    165         x=t;
    166         while (x!=mid)
    167         {
    168             if (x<=n)
    169                 pr[++ans_p]=x;
    170             p=e[x];
    171             while (p)
    172             {
    173                 if (p->cond && p->len)
    174                 {
    175                     x=p->d;
    176                     break;
    177                 }
    178                 p=p->to;
    179             }
    180         }
    181         printf("%d",mid);
    182         for (i=ans_p;i>=1;i--)
    183             printf(" %d",pr[i]);
    184         printf("
    ");
    185     }
    186     return 0;
    187 }
    188 /*
    189 5
    190 
    191 5 5
    192 1 5 3
    193 1 2
    194 2 3
    195 3 4
    196 4 5
    197 5 1
    198 
    199 5 5
    200 1 3 5
    201 1 2
    202 2 3
    203 3 4
    204 4 5
    205 5 1
    206 
    207 3 3
    208 1 2 3
    209 2 1
    210 2 3
    211 3 1
    212 
    213 4 6
    214 2 1 4
    215 1 2
    216 1 3
    217 1 4
    218 2 3
    219 2 4
    220 3 4
    221 
    222 10 10
    223 5 3 10
    224 1 2
    225 2 3
    226 3 4
    227 4 5
    228 5 6
    229 6 7
    230 7 8
    231 8 9
    232 9 10
    233 10 1
    234 
    235 3 0
    236 1 2 3
    237 
    238 5 6
    239 2 1 4
    240 1 2
    241 2 4
    242 4 5
    243 4 3
    244 5 1
    245 3 1
    246 
    247 */

     

    错误代码1

    网络流不拆点删环

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <string>
      5 #include <cmath>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 #include <queue>
     11 const int maxn=1e2+10;
     12 const int inf=1e9;
     13 #include <assert.h>
     14 
     15 /*
     16 不拆点,网络规模减少一半
     17 
     18 输出结果,去环 O(n)
     19 或者用费用流 每条边cost=-1,求最短的路径
     20 费用流时间复杂度?
     21 dinic时间复杂度?
     22 */
     23 
     24 struct node
     25 {
     26     int d,len,cond,visit;
     27     node *to,*opp;
     28 }*e[maxn];
     29 
     30 int ss,tt,mid,q[maxn],dep[maxn];
     31 int ans_p,pr[maxn],pre[maxn];
     32 
     33 void addedge(int x,int y,int z)
     34 {
     35     node *p1,*p2;
     36     p1=new node();
     37     p2=new node();
     38 
     39     p1->d=y;
     40     p1->len=z;
     41     p1->opp=p2;
     42     p1->to=e[x];
     43     e[x]=p1;
     44     p1->cond=0;
     45 
     46     p2->d=x;
     47     p2->len=0;
     48     p2->opp=p1;
     49     p2->to=e[y];
     50     e[y]=p2;
     51     p2->cond=1;
     52 }
     53 
     54 bool bfs()
     55 {
     56     node *p;
     57     int head=0,tail=1,d,dd;
     58     memset(dep,0,sizeof(dep));
     59     dep[ss]=1;
     60     q[1]=ss;
     61     while (head<tail)
     62     {
     63         head++;
     64         d=q[head];
     65         p=e[d];
     66         while (p)
     67         {
     68             dd=p->d;
     69             if (!dep[dd] && p->len)
     70             {
     71                 q[++tail]=dd;
     72                 dep[dd]=dep[d]+1;
     73             }
     74             p=p->to;
     75         }
     76     }
     77     if (dep[tt])
     78         return 1;
     79     return 0;
     80 }
     81 
     82 int dfs(int d,int add)
     83 {
     84     if (!add || d==tt)
     85         return add;
     86     int totr=0,r,dd;
     87     node *p=e[d];
     88     while (p)
     89     {
     90         dd=p->d;
     91         if (dep[dd]==dep[d]+1 && (r=dfs(dd,min(add,p->len)))>0)
     92         {
     93             totr+=r;
     94             add-=r;
     95             p->len-=r;
     96             p->opp->len+=r;
     97         }
     98         p=p->to;
     99     }
    100     return totr;
    101 }
    102 
    103 void print(int x)
    104 {
    105     node *p=e[x];
    106     while (p)
    107     {
    108         if (p->cond && p->len)
    109         {
    110             x=p->d;
    111             if (x!=mid)
    112                 print(x);
    113             break;
    114         }
    115         p=p->to;
    116     }
    117     printf("%d ",x);
    118 }
    119 
    120 int main()
    121 {
    122     node *p;
    123     int T,n,m,x,y,i,s,t,sum;
    124     scanf("%d",&T);
    125     while (T--)
    126     {
    127         scanf("%d%d",&n,&m);
    128         scanf("%d%d%d",&s,&t,&mid);
    129         ss=n+1;
    130         tt=n+2;
    131         for (i=1;i<=n+2;i++)
    132             e[i]=0;
    133         addedge(n+1,mid,2);
    134         addedge(s,n+2,1);
    135         addedge(t,n+2,1);
    136         while (m--)
    137         {
    138             scanf("%d%d",&x,&y);
    139             addedge(x,y,1);
    140             addedge(y,x,1);
    141         }
    142 
    143         sum=0;
    144         while (bfs())
    145             sum+=dfs(ss,inf);
    146 
    147 //        assert(sum==2);
    148 
    149         ///有可能出现环结构 x->y->z->x or others, 去环
    150         memset(pre,0,sizeof(pre));
    151         ans_p=0;
    152         x=s;
    153         while (x!=mid)
    154         {
    155             pr[++ans_p]=x;
    156             p=e[x];
    157             while (p)
    158             {
    159                 if (p->cond && p->len && !p->visit)
    160                 {
    161                     x=p->d;
    162                     p->visit=1;
    163                     break;
    164                 }
    165                 p=p->to;
    166             }
    167             if (pre[x])
    168                 ans_p=pre[x];
    169             else
    170                 pre[x]=ans_p+1;
    171         }
    172         for (i=1;i<=ans_p;i++)
    173             printf("%d ",pr[i]);
    174 
    175         memset(pre,0,sizeof(pre));
    176         ans_p=0;
    177         x=t;
    178         while (x!=mid)
    179         {
    180             pr[++ans_p]=x;
    181             p=e[x];
    182             while (p)
    183             {
    184                 if (p->cond && p->len && !p->visit)
    185                 {
    186                     x=p->d;
    187                     p->visit=1;
    188                     break;
    189                 }
    190                 p=p->to;
    191             }
    192             if (pre[x])
    193                 ans_p=pre[x];
    194             else
    195                 pre[x]=ans_p+1;
    196         }
    197         printf("%d",mid);
    198         for (i=ans_p;i>=1;i--)
    199             printf(" %d",pr[i]);
    200         printf("
    ");
    201 
    202 //        ///100*99=9900 *10 sometimes need
    203 //        node *pp;
    204 //        for (i=1;i<=n+2;i++)
    205 //        {
    206 //            p=e[i];
    207 //            while (p)
    208 //            {
    209 //                p->visit=0;
    210 //                pp=p;
    211 //                p=p->to;
    212 //                free(pp);
    213 //            }
    214 //        }
    215     }
    216     return 0;
    217 }
    218 /*
    219 5
    220 
    221 5 5
    222 1 5 3
    223 1 2
    224 2 3
    225 3 4
    226 4 5
    227 5 1
    228 
    229 5 5
    230 1 3 5
    231 1 2
    232 2 3
    233 3 4
    234 4 5
    235 5 1
    236 
    237 3 3
    238 1 2 3
    239 2 1
    240 2 3
    241 3 1
    242 
    243 4 6
    244 2 1 4
    245 1 2
    246 1 3
    247 1 4
    248 2 3
    249 2 4
    250 3 4
    251 
    252 10 10
    253 5 3 10
    254 1 2
    255 2 3
    256 3 4
    257 4 5
    258 5 6
    259 6 7
    260 7 8
    261 8 9
    262 9 10
    263 10 1
    264 
    265 
    266 
    267 3 0
    268 1 2 3
    269 
    270 
    271 1
    272 5 6
    273 2 1 4
    274 1 2
    275 2 4
    276 4 5
    277 4 3
    278 5 1
    279 3 1
    280 */

    错误代码2

    费用流不拆点

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cstring>
      4 #include <string>
      5 #include <cmath>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 #include <queue>
     11 const int maxn=1e2+10;
     12 const int inf=1e9;
     13 #include <assert.h>
     14 
     15 /*
     16 时间复杂度为O(N*E*k),其中K为最大流值。但时间上的期望时间复杂度为:O(A*E*K),其中A为所有顶点进队列的平均次数,可以证明A一般小于等于2。
     17 */
     18 
     19 struct node
     20 {
     21     int d,len,cost,cond;
     22     node *to,*opp;
     23 }*e[maxn],*pre[maxn];
     24 
     25 int ss,tt,dist[maxn],add[maxn],flow,fee;
     26 bool vis[maxn];
     27 int ans_p,pr[maxn];
     28 
     29 queue<int>st;
     30 
     31 void addedge(int x,int y,int len,int cost)
     32 {
     33     node *p1,*p2;
     34     p1=new node();
     35     p2=new node();
     36 
     37     p1->d=y;
     38     p1->len=len;
     39     p1->cost=cost;
     40     p1->opp=p2;
     41     p1->to=e[x];
     42     p1->cond=0;
     43     e[x]=p1;
     44 
     45     p2->d=x;
     46     p2->len=0;
     47     p2->cost=-cost;
     48     p2->opp=p1;
     49     p2->to=e[y];
     50     p2->cond=1;
     51     e[y]=p2;
     52 }
     53 
     54 void bfs()
     55 {
     56     node *p;
     57     int d,dd;
     58     while (1)
     59     {
     60         memset(dist,0x7f,sizeof(dist));
     61         dist[ss]=0;
     62         add[ss]=inf;
     63         add[tt]=0;
     64 
     65         st.push(ss);
     66         while (!st.empty())
     67         {
     68             d=st.front();
     69             st.pop();
     70             p=e[d];
     71             while (p)
     72             {
     73                 dd=p->d;
     74                 if (p->len && dist[dd]>dist[d]+p->cost)
     75                 {
     76                     dist[dd]=dist[d]+p->cost;
     77                     add[dd]=min(add[d],p->len);
     78                     pre[dd]=p->opp;
     79                     if (!vis[dd])
     80                     {
     81                         vis[dd]=1;
     82                         st.push(dd);
     83                     }
     84                 }
     85                 p=p->to;
     86             }
     87             vis[d]=0;
     88         }
     89 
     90         if (add[tt]==0)
     91             break;
     92 
     93         flow+=add[tt];
     94         fee+=add[tt]*dist[tt];
     95         d=tt;
     96         while (d!=ss)
     97         {
     98             pre[d]->len+=add[tt];
     99             pre[d]->opp->len-=add[tt];
    100             d=pre[d]->d;
    101         }
    102     }
    103 }
    104 
    105 int main()
    106 {
    107     node *p;
    108     int T,n,m,x,y,i,mid,s,t;
    109     scanf("%d",&T);
    110     while (T--)
    111     {
    112         scanf("%d%d",&n,&m);
    113         scanf("%d%d%d",&s,&t,&mid);
    114         ss=n+1;
    115         tt=n+2;
    116         for (i=1;i<=n+2;i++)
    117             e[i]=0;
    118         addedge(n+1,mid,2,1);
    119         addedge(s,n+2,1,1);
    120         addedge(t,n+2,1,1);
    121         while (m--)
    122         {
    123             scanf("%d%d",&x,&y);
    124             if (x!=s && x!=t)
    125                 addedge(x,y,1,1);
    126             if (y!=s && y!=t)
    127                 addedge(y,x,1,1);
    128         }
    129 
    130         flow=0,fee=0;
    131         bfs();
    132 
    133 //        printf("data=%d %d %d
    ",s,t,mid);
    134 
    135         if (flow!=2)
    136         {
    137             printf("-1
    ");
    138             continue;
    139         }
    140 
    141         ans_p=0;
    142         x=s;
    143         while (x!=mid)
    144         {
    145             pr[++ans_p]=x;
    146             p=e[x];
    147             while (p)
    148             {
    149                 if (p->cond && p->len)
    150                 {
    151                     x=p->d;
    152                     break;
    153                 }
    154                 p=p->to;
    155             }
    156         }
    157         for (i=1;i<=ans_p;i++)
    158             printf("%d ",pr[i]);
    159 
    160         ans_p=0;
    161         x=t;
    162         while (x!=mid)
    163         {
    164             pr[++ans_p]=x;
    165             p=e[x];
    166             while (p)
    167             {
    168                 if (p->cond && p->len)
    169                 {
    170                     x=p->d;
    171                     break;
    172                 }
    173                 p=p->to;
    174             }
    175         }
    176         printf("%d",mid);
    177         for (i=ans_p;i>=1;i--)
    178             printf(" %d",pr[i]);
    179         printf("
    ");
    180     }
    181     return 0;
    182 }
    183 /*
    184 5
    185 
    186 5 5
    187 1 5 3
    188 1 2
    189 2 3
    190 3 4
    191 4 5
    192 5 1
    193 
    194 5 5
    195 1 3 5
    196 1 2
    197 2 3
    198 3 4
    199 4 5
    200 5 1
    201 
    202 3 3
    203 1 2 3
    204 2 1
    205 2 3
    206 3 1
    207 
    208 4 6
    209 2 1 4
    210 1 2
    211 1 3
    212 1 4
    213 2 3
    214 2 4
    215 3 4
    216 
    217 10 10
    218 5 3 10
    219 1 2
    220 2 3
    221 3 4
    222 4 5
    223 5 6
    224 6 7
    225 7 8
    226 8 9
    227 9 10
    228 10 1
    229 
    230 3 0
    231 1 2 3
    232 
    233 5 6
    234 2 1 4
    235 1 2
    236 2 4
    237 4 5
    238 4 3
    239 5 1
    240 3 1
    241 
    242 */

    构造时出现的困难:

    1.费用流 不能有负环 从而无法设置更大的负值,从而决定一定要走哪条边

    2.上下界可行流

    想过设置mid->mid+n(可以再加上s->s+n和t->t+n)下界为1

    但是无法做到流形成一条路径

    如d->d+n下界为1,点d与点p相连,则可以为

    sss->d+n->p->p+n->d->ttt

    可以判断dfs形成的解是否为一条从s到t的链,

    但是dfs形成的解太多,时间复杂度无法降下来。

    由于无法解决这个问题,那么进一步的想法也没有意义了:

    设置所有的点 d->d+n,使所有点从必须遍历,随机选择一个起点,终点为其中一个与起点相连的点,求网络流,解为哈密顿回路。

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <set>
      8 #include <map>
      9 #include <queue>
     10 #include <iostream>
     11 using namespace std;
     12 
     13 #define ll long long
     14 
     15 const int maxn=2e2+10;
     16 const int maxm=1e4;
     17 const int inf=1e9;
     18 const double eps=1e-8;
     19 
     20 struct node
     21 {
     22     int d,len,cond;
     23     node *to,*opp;
     24 }*e[maxn];
     25 
     26 int dif[maxn],dep[maxn],q[maxn],n,low[maxm],ss,tt,st,en;
     27 
     28 void addedge(int x,int y,int z)
     29 {
     30 //    printf("===%d %d %d
    ",x,y,z);
     31 
     32     node *p1,*p2;
     33     p1=new node();
     34     p2=new node();
     35 
     36     p1->d=y;
     37     p1->len=z;
     38     p1->opp=p2;
     39     p1->to=e[x];
     40     e[x]=p1;
     41     p1->cond=0;
     42 
     43     p2->d=x;
     44     p2->len=0;
     45     p2->opp=p1;
     46     p2->to=e[y];
     47     e[y]=p2;
     48     p2->cond=1;
     49 }
     50 
     51 bool bfs()
     52 {
     53     node *p;
     54     int head=0,tail=1,d,dd;
     55     memset(dep,0,sizeof(dep));
     56     dep[st]=1;
     57     q[1]=st;
     58     while (head<tail)
     59     {
     60         head++;
     61         d=q[head];
     62         p=e[d];
     63         while (p)
     64         {
     65             dd=p->d;
     66             if (!dep[dd] && p->len)
     67             {
     68                 q[++tail]=dd;
     69                 dep[dd]=dep[d]+1;
     70             }
     71             p=p->to;
     72         }
     73     }
     74     if (dep[en])
     75         return 1;
     76     return 0;
     77 }
     78 
     79 int dfs(int d,int add)
     80 {
     81     if (!add || d==en)
     82         return add;
     83     int totr=0,r,dd;
     84     node *p=e[d];
     85     while (p)
     86     {
     87         dd=p->d;
     88         if (dep[dd]==dep[d]+1 && (r=dfs(dd,min(add,p->len)))>0)
     89         {
     90             totr+=r;
     91             add-=r;
     92             p->len-=r;
     93             p->opp->len+=r;
     94         }
     95         p=p->to;
     96     }
     97     return totr;
     98 }
     99 
    100 int main()
    101 {
    102     node *p;
    103     int T,n,m,x,y,i,mid,s,t,sum,sss,ttt;
    104     scanf("%d",&T);
    105     while (T--)
    106     {
    107         scanf("%d%d",&n,&m);
    108         scanf("%d%d%d",&s,&t,&mid);
    109 
    110         for (i=1;i<=2*n+4;i++)
    111             e[i]=0;
    112         sss=2*n+3;
    113         ttt=2*n+4;
    114         ss=2*n+1;
    115         tt=2*n+2;
    116         addedge(ss,s,1);
    117         addedge(t+n,tt,1);
    118         for (i=1;i<=n;i++)
    119             if (i==mid || i==s || i==t)
    120                 addedge(i,i+n,1-1);
    121             else
    122                 addedge(i,i+n,1);
    123 
    124         addedge(sss,mid+n,1);///
    125         addedge(mid,ttt,1);
    126 
    127         addedge(sss,s+n,1);///
    128         addedge(s,ttt,1);
    129 
    130         addedge(sss,t+n,1);///
    131         addedge(t,ttt,1);
    132 
    133         int tot=1;
    134         while (m--)
    135         {
    136             scanf("%d%d",&x,&y);
    137             addedge(x+n,y,1);
    138             addedge(y+n,x,1);
    139         }
    140 
    141         addedge(tt,ss,inf);
    142 
    143         st=sss,en=ttt;
    144         sum=0;
    145         while (bfs())
    146             sum+=dfs(st,inf);
    147 //        if (sum==tot)
    148 //        {
    149 //            sum=0;
    150 //            st=ss,en=tt;
    151 //            while (bfs())
    152 //                sum+=dfs(st,inf);
    153 
    154             x=s;
    155             while (x!=mid)
    156             {
    157                 if (x<=n)
    158                     printf("%d ",x);
    159                 p=e[x];
    160                 while (p)
    161                 {
    162                     if (!p->cond && p->opp->len)
    163                         break;
    164                     p=p->to;
    165                 }
    166             }
    167             ///
    168             x=mid+n;
    169             while (x!=t)
    170             {
    171                 if (x<=n)
    172                     printf("%d ",x);
    173                 p=e[x];
    174                 while (p)
    175                 {
    176                     if (!p->cond && p->opp->len)
    177                         break;
    178                     p=p->to;
    179                 }
    180             }
    181             printf("%d
    ",t);
    182 
    183 //        }
    184 //        else
    185 //            printf("please go home to sleep");
    186     }
    187     return 0;
    188 }
    189 /*
    190 4 3 1 4
    191 2 3 2 3
    192 1 2 0 100
    193 3 4 0 100
    194 
    195 4 3 1 4
    196 2 3 0 3
    197 1 2 0 100
    198 3 4 0 100
    199 */

    造数据:

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <string>
     5 #include <cmath>
     6 #include <algorithm>
     7 #include <iostream>
     8 using namespace std;
     9 #define ll long long
    10 #include <time.h>
    11 
    12 const int maxn=1e2+10;
    13 
    14 bool vis[maxn][maxn];
    15 int px[maxn*maxn],py[maxn*maxn];
    16 
    17 int main()
    18 {
    19     int t,n,m,x,y,z,i;
    20     srand(time(NULL));
    21     FILE *in=fopen("1.in","w");
    22     t=1000;
    23     fprintf(in,"%d
    ",t);
    24     while (t--)
    25     {
    26         do
    27         {
    28             n=rand()%100+1;
    29         }
    30         while (n<=2);
    31         m=rand()%(n*(n-1)/2)+1;
    32 
    33         x=rand()%n+1;
    34         do
    35             y=rand()%n+1;
    36         while (y==x);
    37         do
    38             z=rand()%n+1;
    39         while (z==x || z==y);
    40 
    41         fprintf(in,"%d %d
    ",n,m);
    42         fprintf(in,"%d %d %d
    ",x,y,z);
    43 
    44 
    45         memset(vis,0,sizeof(vis));
    46         for (i=1;i<=m;)
    47         {
    48             x=rand()%n+1;
    49             do
    50                 y=rand()%n+1;
    51             while (y==x);
    52             if (!vis[x][y])
    53             {
    54                 px[i]=x,py[i]=y;
    55                 i++;
    56             }
    57         }
    58         for (i=1;i<=m;i++)
    59             fprintf(in,"%d %d
    ",px[i],py[i]);
    60         fprintf(in,"
    ");
    61     }
    62     fclose(in);
    63     return 0;
    64 }

    练习题:

    P2045 方格取数加强版

    https://www.luogu.org/problemnew/show/P2045

    获得最大值需要的最少部分(自己造的!)

    网络流+二分

  • 相关阅读:
    61. 最长不含重复字符的子字符串
    60. 礼物的最大价值 (未理解)
    59. 把数字翻译成字符串
    58. 把数组排成最小的数
    57. 数字序列中某一位的数字 (不懂)
    spring data jpa 官方文档
    idea 编译报错 源发行版 1.8 需要目标发行版 1.8
    idea maven 依赖报错 invalid classes root
    solr
    spring boot 官方文档
  • 原文地址:https://www.cnblogs.com/cmyg/p/11053148.html
Copyright © 2011-2022 走看看