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

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

    网络流+二分

  • 相关阅读:
    GitLab 重置认证和添加账号缓存
    PHP 正则匹配IP
    git 删除指定版本
    PostgreSQL 9.2 日期运算
    postgre 已有字段修改为自增
    postgresql 导入导出
    PHP TS 和 NTS 版本选择
    background-image属性的设置
    SQLServer 附加数据库后只读或报错解决方法
    IIS 6.0 发布网站使用教程
  • 原文地址:https://www.cnblogs.com/cmyg/p/11053148.html
Copyright © 2011-2022 走看看