• BZOJ2324 ZJOI2011营救皮卡丘(floyd+上下界费用流)


      虽然不一定每次都是由编号小的点向编号大的走,但一个人摧毁的顺序一定是从编号小的到编号大的。那么在摧毁据点x的过程中,其只能经过编号小于x的点。并且这样一定合法,因为可以控制其他人先去摧毁所经过的点。那么可以floyd求出由摧毁x到摧毁y的最短路径。注意这里也需要更新起点编号大于终点的情况,否则floyd会挂掉。

      剩下的问题就是用k条路径覆盖所有点使费用最小。那么考虑网络流。可以将每个点拆成入点和出点来控制节点流量至少为1,边权的费用设置为其间最短路径,跑上下界费用流即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    #define N 310
    #define M 20010
    #define S 302
    #define T 303
    #define in(x) (x<<1)
    #define out(x) (x<<1|1)
    int n,m,k,p[N],dis[N][N],t=-1,ans=0;
    int d[N],q[N],pre[N];
    bool flag[N];
    struct data{int to,nxt,cap,flow,cost;
    }edge[M<<3];
    void addedge(int x,int y,int z,int c)
    {
        t++;edge[t].to=y,edge[t].nxt=p[x],edge[t].cap=z,edge[t].flow=0,edge[t].cost=c,p[x]=t;
        t++;edge[t].to=x,edge[t].nxt=p[y],edge[t].cap=0,edge[t].flow=0,edge[t].cost=-c,p[y]=t;
    }
    int inc(int &x){x++;if (x>T+2) x-=T+2;return x;}
    bool spfa()
    {
        memset(d,42,sizeof(d));d[S]=0;
        memset(flag,0,sizeof(flag));
        int head=0,tail=1;q[1]=S;
        do
        {
            int x=q[inc(head)];flag[x]=0;
            for (int i=p[x];~i;i=edge[i].nxt)
            if (d[x]+edge[i].cost<d[edge[i].to]&&edge[i].flow<edge[i].cap)
            {
                d[edge[i].to]=d[x]+edge[i].cost;
                pre[edge[i].to]=i;
                if (!flag[edge[i].to]) q[inc(tail)]=edge[i].to,flag[edge[i].to]=1;
            }
        }while (head!=tail);
        return d[T]<=700000000;
    }
    void ekspfa() 
    {
        while (spfa())
        {
            int v=k;
            for (int i=T;i!=S;i=edge[pre[i]^1].to)
            v=min(v,edge[pre[i]].cap-edge[pre[i]].flow);
            for (int i=T;i!=S;i=edge[pre[i]^1].to)
            ans+=v*edge[pre[i]].cost,edge[pre[i]].flow+=v,edge[pre[i]^1].flow-=v;
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj2324.in","r",stdin);
        freopen("bzoj2324.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read(),m=read(),k=read();
        memset(p,255,sizeof(p));
        memset(dis,42,sizeof(dis));
        for (int i=0;i<=n;i++) dis[i][i]=0;
        for (int i=1;i<=m;i++)
        {
            int x=read(),y=read(),z=read();
            dis[x][y]=dis[y][x]=min(dis[x][y],z);
        }
        for (int k=0;k<=n;k++)
            for (int i=0;i<=n;i++)
                for (int j=0;j<=n;j++)
                if (i>=k||j>=k) dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
        for (int i=0;i<n;i++)
            for (int j=i+1;j<=n;j++)
            addedge(out(i),in(j),k,dis[i][j]);
        for (int i=0;i<=n;i++)
        addedge(in(i),out(i),k,0);
        for (int i=0;i<=n;i++)
        addedge(in(i),T,1,0),addedge(S,out(i),1,0),addedge(out(i),out(n),k,0);
        addedge(out(n),in(0),k,0);
        ekspfa();
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    spring之aop概念和配置
    netty概念
    maven使用实例记录
    maven概念
    Runtime.getRuntime().addShutdownHook
    aop前传之代理
    实例化bean的三种方式
    easyui datagrid treegrid 取消行选中、取消高亮
    sqlserver 保存 立方米(m³)
    sqlserver 备份集中的数据库备份与现有的 'XXX' 数据库不同。
  • 原文地址:https://www.cnblogs.com/Gloid/p/9563962.html
Copyright © 2020-2023  润新知