zoukankan      html  css  js  c++  java
  • Day66:POJ2135Farm Tour(最小费用最大流模板题)SPFA+MCMF

    题意:

    给出n个点,m条边,问一个人从家走到barn的最短长度(设家1,barn为N);
    所以,问的就是   去:1->N     和     返:N->1     两条路径的最短长度,两条路径不能重复;
    所以,问题变成了:有两个人,从1->N,它们所走路径不能重复(走的边不能重复),求最短长度。

    所以变成了最小费用最大流问题,自己再自己想想。

     思路:

    我以为是个最短路。。但是最短路貌似好像不能解决路径重复问题叭。。

    妥妥的模板,我终于碰到了,原来我先做的都是变形题,我太难了。。

    题意转化到算法上还是比较不好想到,怎么分析在上面的题意里面已经写清楚了。

    容量cap传入的为1或者2(自己判断传入什么),花费cost即点和点之间的权值。

    建边最重要:

    scanf("%d %d",&n,&m);
    tot=0,s=0,t=n+1;
    memset(head,-1,sizeof(head));
    for(int i=1; i<=m; i++)
    {
        int u,v,w;
        scanf("%d %d %d",&u,&v,&w);
        add(u,v,1,w);//cap,cost
        add(v,u,1,w);
    }
    add(s,1,2,0);
    add(n,t,2,0);

    邻接表建边:

     1 void add(int u,int v,int cap,int cost)
     2 {
     3     e[tot].to=v;
     4     e[tot].nextt=head[u];
     5     e[tot].cap=cap;
     6     e[tot].cost=cost;
     7     e[tot].flow=0;
     8     head[u]=tot++;
     9 
    10     e[tot].to=u;
    11     e[tot].nextt=head[v];
    12     e[tot].cap=0;
    13     e[tot].cost=-cost;
    14     e[tot].flow=0;
    15     head[v]=tot++;
    16 
    17 }
    View Code

    SPFA:

     1 bool SPFA()
     2 {
     3     for(int i=0; i<=t; i++)
     4     {
     5         dist[i]=inf;
     6         book[i]=0;
     7         pre[i]=-1;//head不能放在这里i清,否则为0
     8     }
     9     book[s]=1;
    10     dist[s]=0;
    11     queue<int>Q;
    12     Q.push(s);
    13     while(!Q.empty())
    14     {
    15         int u=Q.front();
    16         Q.pop();
    17         book[u]=0;
    18         for(int i=head[u]; i!=-1; i=e[i].nextt)
    19         {
    20             int v=e[i].to;
    21             if(e[i].cap>e[i].flow&&dist[v]>dist[u]+e[i].cost)
    22             {
    23                 dist[v]=dist[u]+e[i].cost;
    24                 pre[v]=i;
    25                 if(book[v]==0)
    26                 {
    27                     book[v]=1;
    28                     Q.push(v);
    29                 }
    30             }
    31         }
    32     }
    33     if(dist[t]!=inf)
    34         return 1;
    35     return 0;
    36 }
    View Code

    MCMF:

     1 int MCMF()
     2 {
     3     int flow=0,cost=0;
     4     while(SPFA())
     5     {
     6         int minn=inf;
     7         for(int i=pre[t]; i!=-1; i=pre[e[i^1].to])
     8             minn=min(minn,e[i].cap-e[i].flow);
     9         for(int i=pre[t]; i!=-1; i=pre[e[i^1].to])
    10         {
    11             e[i].flow+=minn;
    12             e[i^1].flow-=minn;
    13             cost+=e[i].cost*minn;
    14         }
    15         flow+=minn;
    16     }
    17     return cost;
    18 }
    View Code

    AC代码:

      1 #include<stdio.h>
      2 #include<iostream>
      3 #include<queue>
      4 #include<string.h>
      5 using namespace std;
      6 #define inf 0x3f3f3f3f
      7 
      8 const int N=1010;
      9 bool book[N];
     10 int n,m,tot,s,t,pre[10*N],head[10*N],dist[10*N];
     11 struct node
     12 {
     13     int to,nextt,cap,flow,cost;
     14 } e[N*N];
     15 
     16 void add(int u,int v,int cap,int cost)
     17 {
     18     e[tot].to=v;
     19     e[tot].nextt=head[u];
     20     e[tot].cap=cap;
     21     e[tot].cost=cost;
     22     e[tot].flow=0;
     23     head[u]=tot++;
     24 
     25     e[tot].to=u;
     26     e[tot].nextt=head[v];
     27     e[tot].cap=0;
     28     e[tot].cost=-cost;
     29     e[tot].flow=0;
     30     head[v]=tot++;
     31 
     32 }
     33 
     34 bool SPFA()
     35 {
     36     for(int i=0; i<=t; i++)
     37     {
     38         dist[i]=inf;
     39         book[i]=0;
     40         pre[i]=-1;//head不能放在这里i清,否则为0
     41     }
     42     book[s]=1;
     43     dist[s]=0;
     44     queue<int>Q;
     45     Q.push(s);
     46     while(!Q.empty())
     47     {
     48         int u=Q.front();
     49         Q.pop();
     50         book[u]=0;
     51         for(int i=head[u]; i!=-1; i=e[i].nextt)
     52         {
     53             int v=e[i].to;
     54             if(e[i].cap>e[i].flow&&dist[v]>dist[u]+e[i].cost)
     55             {
     56                 dist[v]=dist[u]+e[i].cost;
     57                 pre[v]=i;
     58                 if(book[v]==0)
     59                 {
     60                     book[v]=1;
     61                     Q.push(v);
     62                 }
     63             }
     64         }
     65     }
     66     if(dist[t]!=inf)
     67         return 1;
     68     return 0;
     69 }
     70 
     71 int MCMF()
     72 {
     73     int flow=0,cost=0;
     74     while(SPFA())
     75     {
     76         int minn=inf;
     77         for(int i=pre[t]; i!=-1; i=pre[e[i^1].to])
     78             minn=min(minn,e[i].cap-e[i].flow);
     79         for(int i=pre[t]; i!=-1; i=pre[e[i^1].to])
     80         {
     81             e[i].flow+=minn;
     82             e[i^1].flow-=minn;
     83             cost+=e[i].cost*minn;
     84         }
     85         flow+=minn;
     86     }
     87     return cost;
     88 }
     89 
     90 int main()
     91 {
     92     scanf("%d %d",&n,&m);
     93     tot=0,s=0,t=n+1;
     94     memset(head,-1,sizeof(head));
     95     for(int i=1; i<=m; i++)
     96     {
     97         int u,v,w;
     98         scanf("%d %d %d",&u,&v,&w);
     99         add(u,v,1,w);//cap,cost
    100         add(v,u,1,w);
    101     }
    102     add(s,1,2,0);
    103     add(n,t,2,0);
    104     int ans=MCMF();
    105     printf("%d\n",ans);
    106     return 0;
    107 }
    View Code
  • 相关阅读:
    题解:CF1494 F. Delete The Edges
    「CEOI2011」选做
    题解:「CEOI2017」Chase
    学习笔记:《具体数学》问题整理
    题解:「COCI2019」 Transport
    【做题记录】位运算
    线性DP
    虚树 virtual-tree
    三元环计数
    长链剖分
  • 原文地址:https://www.cnblogs.com/OFSHK/p/12655707.html
Copyright © 2011-2022 走看看