1. 程式人生 > >BZOJ_1877_[SDOI2009]晨跑_費用流

BZOJ_1877_[SDOI2009]晨跑_費用流

line sizeof tdi bzoj highlight string 十字路口 pat ont

BZOJ_1877_[SDOI2009]晨跑_費用流

題意:

Elaxia最近迷戀上了空手道,他為自己設定了一套健身計劃,比如俯臥撐、仰臥起坐等 等,不過到目前為止,他 堅持下來的只有晨跑。 現在給出一張學校附近的地圖,這張地圖中包含N個十字路口和M條街道,Elaxia只能從 一 個十字路口跑向另外一個十字路口,街道之間只在十字路口處相交。Elaxia每天從寢室出發 跑到學校,保證寢室 編號為1,學校編號為N。 Elaxia的晨跑計劃是按周期(包含若幹天)進行的,由於他不喜歡走重復的路線,所以 在一個周期內,每天的晨跑路線都不會相交(在十字路口處),寢室和學校不算十字路 口。Elaxia耐力不太好, 他希望在一個周期內跑的路程盡量短,但是又希望訓練周期包含的天 數盡量長。 除了練空手道,Elaxia其他時間 都花在了學習和找MM上面,所有他想請你幫忙為他設計 一套滿足他要求的晨跑計劃。 分析: 費用流。 拆個點,入點到出點連容量1的邊。 代碼:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 550
#define M 180050
#define S (n+1)
#define T (n)
#define inf 100000000
int head[N],to[M],nxt[M],flow[M],val[M],cnt=1,n,m;
int Q[N],l,r,dis[N],path[N],inq[N];
inline void add(int u,int v,int f,int w){
    to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;flow[cnt]=f;val[cnt]=w;
    to[++cnt]=u;nxt[cnt]=head[v];head[v]=cnt;flow[cnt]=0;val[cnt]=-w;
}
bool spfa(){
    memset(dis,0x3f,sizeof(dis));memset(path,0,sizeof(path));l=r=0;
    Q[r++]=S;dis[S]=0;inq[S]=1;
    while(l^r){
        int x=Q[l++];inq[x]=0;if(l==n+n+10)l=0;
        for(int i=head[x];i;i=nxt[i]){
            if(flow[i]>0&&dis[to[i]]>dis[x]+val[i]){
                dis[to[i]]=dis[x]+val[i];
                path[to[i]]=i^1;
                if(!inq[to[i]]){
                    inq[to[i]]=1;Q[r++]=to[i];if(r==n+n+10)r=0;
                }
            }
        }
    }
    return dis[T]<inf;
}
void mcmf(){
    int minc=0,maxf=0;
    while(spfa()){
        minc+=dis[T];
        for(int i=T;i!=S;i=to[path[i]]){
            flow[path[i]]++;
            flow[path[i]^1]--;
        }
        maxf++;
    }
    printf("%d %d\n",maxf,minc);
}
int main(){
    scanf("%d%d",&n,&m);
    int x,y,z;
    for(int i=1;i<=n;i++)add(i,i+n,1,0);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&x,&y,&z);
        add(x+n,y,1,z);
    }
    mcmf();
}

BZOJ_1877_[SDOI2009]晨跑_費用流