zoukankan      html  css  js  c++  java
  • 【Luogu】P2469星际竞速(费用流)

      题目链接

      费用流,类似最小路径覆盖。

      从起点向i连一条容量1费用0的边,从i'向终点连一条容量1费用0的边;

      从起点向i'连一条容量1费用为瞬移的边,从i向j'连一条容量1费用为边权的边。

      然后跑就可以了。

    #include<cstdio>
    #include<cstdlib>
    #include<cctype>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define maxn 200020
    using namespace std;
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    struct Edge{
        int next,from,to,val,dis;
    }edge[maxn];
    int head[maxn],num;
    inline void addedge(int from,int to,int val,int dis){
        edge[++num]=(Edge){head[from],from,to,val,dis};
        head[from]=num;
    }
    inline void add(int from,int to,int val,int dis){
        addedge(from,to,val,dis);
        addedge(to,from,0,-dis);
    }
    
    inline int count(int i){    return i&1?i+1:i-1;    }
    
    int dis[maxn];
    int pre[maxn];
    bool vis[maxn];
    int Start,End;
    
    int spfa(){
        memset(dis,127/3,sizeof(dis));    dis[Start]=0;
        memset(pre,0,sizeof(pre));
        queue<int>q;    q.push(Start);
        while(!q.empty()){
            int from=q.front();    q.pop();    vis[from]=0;
            //printf("%d
    ",from);
            for(int i=head[from];i;i=edge[i].next){
                int to=edge[i].to;
                if(edge[i].val<=0||dis[to]<=dis[from]+edge[i].dis)    continue;
                dis[to]=dis[from]+edge[i].dis;
                pre[to]=i;
                if(vis[to])    continue;
                vis[to]=1;    q.push(to);
            }
        }
        if(pre[End]==0)    return 0;
        int now=End;
        while(now!=Start){
            int ret=pre[now];
            edge[ret].val--;    edge[count(ret)].val++;
            now=edge[ret].from;
        }
        return dis[End];
    }
    
    int main(){
        int n=read(),m=read();
        End=n*2+1;
        for(int i=1;i<=n;++i){
            add(Start,i+n,1,read());
            add(Start,i,1,0);
            add(i+n,End,1,0);
        }
        for(int i=1;i<=m;++i){
            int from=read(),to=read(),val=read();
            if(from>to)    swap(from,to);
            add(from,to+n,1,val);
        }
        int ans=0;
        while(1){
            int now=spfa();
            if(now==0)    break;
            ans+=now;
        }
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    查看Oracle字符集
    Oracle备份还原表须知
    Oracle级联删除,删除用户的同时,将所分配到的表空间同时删除
    python logging模块(1) Marathon
    pycharm中调试django程序 Marathon
    sqlite数据表的增删改查操作 Marathon
    ubuntu 18.04配置固定ip Marathon
    django项目报错request请求不能处理问题 Marathon
    systemd.service配置 Marathon
    shell脚本学习之6小时搞定(1)入门 Marathon
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8881907.html
Copyright © 2011-2022 走看看