• UVa 1658,Admiral (拆点+限制最小费用流)


    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=569&problem=4277&mosmsg=Submission+received+with+ID+2182664

    题目大意:给定一个带权有向图(v,e),求两条互不相交的从1到v的路径(不经过同一个点),使两条路径的权和最小.

    分析:即求从1到v的最小费用流,到v的流量为2,且每个点只能经过一次.加一个从v出发的点v',费用为0,容量为2,求1到v'的最小费用流即满足前一条件;将2到v-1每个点拆分成两个点,费用为0,容量为1,再求从1到v'的最小费用流即可.

      一定要注意求mcmf时设置的INF要恰当!!!不然就溢出然后疯狂WA了!!!

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<vector>
     5 #include<queue>
     6 using namespace std;
     7 const int maxn=2005,maxm=20005,INF=1000000;
     8 struct Edge{
     9     int from,to,cap,flow,cost;
    10     Edge(int u,int v,int c,int f,int w):from(u),to(v),cap(c),flow(f),cost(w){}
    11 };
    12 
    13 struct MCMF{
    14     int n,m;
    15     vector<Edge> edges;
    16     vector<int> G[maxn];
    17     int inq[maxn],d[maxn],p[maxn],a[maxn];
    18 
    19     void init(int n){
    20         this->n=n;
    21         this->m=0;
    22         for(int i=0;i<n;i++)G[i].clear();
    23         edges.clear();
    24     }
    25 
    26     void AddEdge(int from,int to,int cap,int cost){
    27         edges.push_back(Edge(from,to,cap,0,cost));
    28         edges.push_back(Edge(to,from,0,0,-cost));
    29         G[from].push_back(this->m++);
    30         G[to].push_back(this->m++);
    31     }
    32 
    33     bool BellmanFord(int s,int t,int &flow,long long &cost){
    34         for(int i=0;i<n;i++)d[i]=INF;
    35         memset(inq,0,sizeof(inq));
    36         d[s]=0;inq[s]=1;p[s]=0;a[s]=INF;
    37         queue<int> Q;
    38         Q.push(s);
    39         while(!Q.empty()){
    40             int u=Q.front();Q.pop();
    41             inq[u]=0;
    42 
    43             for(int i=0;i<G[u].size();i++){
    44                 Edge &e=edges[G[u][i]];
    45                 if(e.cap>e.flow&&d[e.to]>d[u]+e.cost){
    46                     d[e.to]=d[u]+e.cost;
    47                     p[e.to]=G[u][i];
    48                     a[e.to]=min(a[u],e.cap-e.flow);
    49                     if(!inq[e.to]){Q.push(e.to);inq[e.to]=1;}
    50                 }
    51             }
    52         }
    53         if(d[t]==INF)return false;
    54         flow+=a[t];
    55         cost+=(long long)d[t]*(long long)a[t];
    56         for(int u=t;u!=s;u=edges[p[u]].from){
    57             edges[p[u]].flow+=a[t];
    58             edges[p[u]^1].flow-=a[t];
    59         }
    60         return true;
    61     }
    62 
    63     int Mincost(int s,int t,long long &cost){
    64         int flow=0;cost=0;
    65         while(BellmanFord(s,t,flow,cost));
    66         return flow;
    67     }
    68 };
    69 
    70 int main(){
    71     //freopen("e:\in.txt","r",stdin);
    72     int n,m,a,b,c;
    73     MCMF mcmf;
    74     mcmf.init(2*n);
    75     for(int i=1;i<n-1;i++){
    76         mcmf.AddEdge(i,i+n,1,0);
    77     }
    78     for(int i=0;i<m;i++){
    79         cin>>a>>b>>c;
    80         a--;b--;
    81         if(a==0||a==n-1){
    82             mcmf.AddEdge(a,b,1,c);
    83         }
    84         else{
    85             mcmf.AddEdge(a+n,b,1,c);
    86         }
    87     }
    88     mcmf.AddEdge(n-1,2*n-1,2,0);
    89     long long cost=0;
    90     mcmf.Mincost(0,2*n-1,cost);
    91     cout<<cost<<endl;
    92     return 0;
    93 }
  • 相关阅读:
    tips
    数学建模-预测模型优缺(搬运)
    数学建模-灰色预测模型GM(1,1)_MATLAB
    Floyd算法_MATLAB
    第二章 运算方法与运算器(浮点数的加减法,IEEE754标准32/64浮点规格化数)
    面向对象
    for循环
    if---else
    airflow的web任务管理
    airflow原理
  • 原文地址:https://www.cnblogs.com/7391-KID/p/6877670.html
Copyright © 2020-2023  润新知