zoukankan      html  css  js  c++  java
  • bzoj 1877 [SDOI2009]晨跑(最小费用最大流)

     

    Description

    Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑、仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑。 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从 一个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交。Elaxia每天从寝室出发 跑到学校,保证寝室编号为1,学校编号为N。 Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以 在一个周期内,每天的晨跑路线都不会相交(在十字路口处),寝室和学校不算十字路 口。Elaxia耐力不太好,他希望在一个周期内跑的路程尽量短,但是又希望训练周期包含的天 数尽量长。 除了练空手道,Elaxia其他时间都花在了学习和找MM上面,所有他想请你帮忙为他设计 一套满足他要求的晨跑计划。

    Input

    第一行:两个数N,M。表示十字路口数和街道数。 接下来M行,每行3个数a,b,c,表示路口a和路口b之间有条长度为c的街道(单向)。

    Output

    两个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长 度。

    Sample Input

    7 10
    1 2 1
    1 3 1
    2 4 1
    3 4 1
    4 5 1
    4 6 1
    2 5 5
    3 6 6
    5 7 1
    6 7 1

    Sample Output

    2 11

    HINT

    对于30%的数据,N ≤ 20,M ≤ 120。
    对于100%的数据,N ≤ 200,M ≤ 20000。

    【思路】

           最小费用最大流

           拆个点,两点之间连容量1费用0的边保证每个结点只经过一次。按照给的图连边跑一次最小费用最大流就好了,保证了流量最大的情况下费用最小。

    【代码】

     1 #include<cmath>
     2 #include<queue>
     3 #include<vector>
     4 #include<cstdio>
     5 #include<cstring>
     6 #include<iostream>
     7 #include<algorithm>
     8 #define FOR(a,b,c) for(int a=(b);a<=(c);a++)
     9 using namespace std;
    10 
    11 const int N = 500+5;
    12 const int INF = 1e9;
    13 
    14 struct Edge {
    15     int u,v,cap,flow,cost;
    16 };
    17 struct MCMF {
    18     queue<int> q;
    19     int n,m,a[N],d[N],p[N],inq[N];
    20     vector<Edge> es; vector<int> g[N];
    21     void init(int n) {
    22         this->n=n;
    23         es.clear(); 
    24         for(int i=0;i<n;i++) g[i].clear();
    25     }
    26     void AddEdge(int u,int v,int cap,int cost) {
    27         es.push_back((Edge){u,v,cap,0,cost});
    28         es.push_back((Edge){v,u,0,0,-cost});
    29         int m=es.size();
    30         g[u].push_back(m-2),g[v].push_back(m-1);
    31     }
    32     bool spfa(int s,int t,int& flow,int& cost) {
    33         memset(inq,0,sizeof(inq));
    34         for(int i=0;i<n;i++) d[i]=INF;
    35         d[s]=0; inq[s]=1; q.push(s); a[s]=INF;
    36         while(!q.empty()) {
    37             int u=q.front(); q.pop(); inq[u]=0;
    38             for(int i=0;i<g[u].size();i++) {
    39                 Edge& e=es[g[u][i]];
    40                 int v=e.v;
    41                 if(e.cap>e.flow && d[v]>d[u]+e.cost) {
    42                     d[v]=d[u]+e.cost;
    43                     p[v]=g[u][i];
    44                     a[v]=min(a[u],e.cap-e.flow);
    45                     if(!inq[v]) inq[v]=1,q.push(v);
    46                 }
    47             }
    48         }
    49         if(d[t]==INF) return 0;
    50         flow+=a[t]; cost+=a[t]*d[t];
    51         for(int x=t;x!=s;x=es[p[x]].u)
    52             es[p[x]].flow+=a[t],es[p[x]^1].flow-=a[t];
    53         return 1;
    54     }
    55     void mcmf(int s,int t,int& flow,int& cost) {
    56         flow=cost=0;
    57         while(spfa(s,t,flow,cost)) ;
    58     }
    59 }mc;
    60 
    61 int n,m;
    62 
    63 int main() {
    64     scanf("%d%d",&n,&m);
    65     mc.init(n*2+2);
    66     int u,v,w,S=1,T=n+n,flow,cost;
    67     for(int i=0;i<m;i++) {
    68         scanf("%d%d%d",&u,&v,&w);
    69         mc.AddEdge(u+n,v,1,w);
    70     }
    71     for(int i=2;i<=n;i++)
    72         mc.AddEdge(i,i+n,1,0);
    73     mc.AddEdge(S,1+n,INF,0);
    74     mc.AddEdge(n,T,INF,0);
    75     mc.mcmf(S,T,flow,cost);
    76     printf("%d %d",flow,cost);
    77     return 0;
    78 }
  • 相关阅读:
    sql语句性能优化
    Windows版Redis如何使用?(单机)
    redis在项目中的使用(单机版、集群版)
    在windows上搭建redis集群(redis-cluster)
    Jenkins打包Maven项目
    numpy交换列
    Linq中join多字段匹配
    SpringMVC Web项目升级为Springboot项目(二)
    SpringMVC Web项目升级为Springboot项目(一)
    springboot读取application.properties中自定义配置
  • 原文地址:https://www.cnblogs.com/lidaxin/p/5225315.html
Copyright © 2011-2022 走看看