其他分享
首页 > 其他分享> > [SDOI2009] 晨跑

[SDOI2009] 晨跑

作者:互联网

[SDOI2009] 晨跑

晨跑?是该减肥了

正文

这真的是道水题。按照常理,我讲讲我的想法。

首先,不难看出这题是到图论的题。然后,他的要求是在各个路径上每个结点都不能相遇。所以自然想到拆点。注意结点的编号。然后,就没什么重要的。

/* make by ltao */
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <deque>
#include <stack>
#include <cmath>
#include <vector>
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
#define sz 666666
#define fake int
#define get() getchar()
int read(){
    int x=0;bool f=0;
    char ch=get();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=1;
        ch=get();
    }
    while(ch<='9'&&ch>='0'){
        x=(x<<1)+(x<<3)+(ch-'0');
        ch=get();
    }
    return f?-x:x;
}
using namespace std;
const int Maxn=404,Maxm=1e5+11;
int n,m,h[Maxn],s,t,x,y,z,cur[Maxn],cnt,maxflow,mincost,dis[Maxn];
bool vis[Maxn];
struct Edge{
    int fr,to,lac,flow,cost;
    void insert(int x,int y,int z,int w){
        to=y;fr=x;
        lac=h[x];h[x]=cnt++;
        flow=z;cost=w;
    }
}edge[Maxm];
int mappn(int u){return u==1?1:u==n?u*2-2:u*2-1;}//后面的点
int mapp1(int u){return u==1?u:u*2-2;}//前面的点
int val=-1;// slf 优化 
bool spfa(int s,int t){
    memset(dis,63,sizeof dis);
    memcpy(cur,h,sizeof cur);
    deque<int> q;q.push_back(s);dis[s]=0;vis[s]=1;
    while(!q.empty()){
        int fr=q.front();
        q.pop_front();vis[fr]=0;
        for(int i=h[fr];i!=-1;i=edge[i].lac){
            int to=edge[i].to;
            if(edge[i].flow&&dis[to]>dis[fr]+edge[i].cost){
                dis[to]=dis[fr]+edge[i].cost;
                if(!vis[to]){
                    vis[to]=1;
                    if(q.size()>0)
                        if(dis[to]-val>=dis[*(q.begin())]) q.push_back(to);
                        else q.push_front(to);
                    else q.push_back(to);
                } 
            }
        }
    }
    return dis[t]!=0x3f3f3f3f;
}
int dfs(int u,int min1){
    if(u==t) return min1;
    int sum=min1;vis[u]=1;
    for(int i=cur[u];i!=-1;i=edge[i].lac){
        int to=edge[i].to;
        if(!edge[i].flow||vis[to]||dis[u]+edge[i].cost!=dis[to]) continue;
        cur[u]=i;int ret=dfs(to,min(sum,edge[i].flow));
        sum-=ret;edge[i].flow-=ret;edge[i^1].flow+=ret;mincost+=ret*edge[i].cost;
        if(!sum)  break;
    }
    vis[u]=0;
    return min1-sum; 
}
void zkwDinic(int s,int t){
    while(spfa(s,t))
        maxflow+=dfs(s,0x3f3f3f3f);
}
int main(){
    freopen("a.in","r",stdin);
    n=read();m=read();s=1;t=n*2-2;memset(h,-1,sizeof h);
    for(int i=2;i<n;i++){
        edge[cnt].insert(i*2-2,i*2-1,1,0);
        edge[cnt].insert(i*2-1,i*2-2,0,0);
    }
    //拆点
    for(int i=1;i<=m;i++){
        x=read();y=read();z=read();
        x=mappn(x);y=mapp1(y);
        edge[cnt].insert(x,y,1,z);
        edge[cnt].insert(y,x,0,-z);
    }
    zkwDinic(s,t);
    printf("%d %d",maxflow,mincost);
    return 0;
}

话说zkw真是有用

我还是喜欢胖胖的我

标签:int,sum,晨跑,vis,edge,SDOI2009,include,dis
来源: https://www.cnblogs.com/zhltao/p/12339793.html