zoukankan      html  css  js  c++  java
  • BZOJ1877: [SDOI2009]晨跑

    【传送门:BZOJ1877


    简要题意:

      给出n个点,起点为1,终点为n,给出m条边,每条边都有费用

      每个点只能走一次,请问最多有多少次机会能从起点到终点,并且求出这几次的最小费用和


    题解:

      一开始还担心有环,实际上没有

      最小费用最大流

      我们将每个点(除了源点和汇点)都拆成两个点x,y,并且x,y之间的流量为1,费用为0,这样就保证每个点只走一次,并且不影响费用

      然后就直接跑费用流,每找到一条增广路就相当于多一次机会,将每条增广路的最小费用加起来即可

      空间和小错误卡了很久


    参考代码:

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    struct node
    {
        int x,y,d,c,next,other;
    }a[1100000];int len,last[110000];
    void ins(int x,int y,int d,int c)
    {
        int k1=++len,k2=++len;
        a[k1].x=x;a[k1].y=y;a[k1].d=d;a[k1].c=c;
        a[k1].next=last[x];last[x]=k1;
        a[k2].x=y;a[k2].y=x;a[k2].d=-d;a[k2].c=0;
        a[k2].next=last[y];last[y]=k2;
        a[k1].other=k2;
        a[k2].other=k1;
    }
    int d[110000],pre[110000],pos[110000];
    bool v[110000];
    int list[110000];
    int st,ed;
    bool spfa()
    {
        for(int i=st;i<=ed;i++) d[i]=999999999;
        d[st]=0;
        memset(v,false,sizeof(v));
        v[st]=true;
        list[1]=st;
        int head=1,tail=2;
        while(head!=tail)
        {
            int x=list[head];
            for(int k=last[x];k;k=a[k].next)
            {
                int y=a[k].y;
                if(a[k].c>0&&d[y]>d[x]+a[k].d)
                {
                    d[y]=d[x]+a[k].d;
                    pos[y]=x;
                    pre[y]=k;
                    if(v[y]==false)
                    {
                        v[y]=true;
                        list[tail++]=y;
                    }
                }
            }
            head++;
            v[x]=false;
        }
        if(d[ed]==999999999) return false;
        else return true;
    }
    int ans,t;
    void Flow()
    {
        while(spfa())
        {
            t++;
            ans+=d[ed];
            int x;
            for(x=ed;x!=st;x=pos[x])
            {
                a[pre[x]].c--;
                a[a[pre[x]].other].c++;
            }
        }
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&m);
        len=0;memset(last,0,sizeof(last));
        for(int i=1;i<=m;i++)
        {
            int x,y,d;
            scanf("%d%d%d",&x,&y,&d);
            if(x==1) ins(x,2*(y-1),d,1);
            else ins(2*(x-1)+1,2*(y-1),d,1);
        }
        for(int i=2;i<n;i++) ins(2*(i-1),2*(i-1)+1,0,1);
        st=1;ed=2*(n-1);
        ans=t=0;
        Flow();
        printf("%d %d
    ",t,ans);
        return 0;
    }

     

  • 相关阅读:
    8.使用axios实现登录功能
    7.django配置跨域并开发测试接口
    9.Vue组件
    2.初始化项目结构
    1.Django基础
    团队冲刺——第七天
    团队冲刺——第六天
    十天冲刺——第五天
    十天冲刺——第四天
    十天冲刺——第三天
  • 原文地址:https://www.cnblogs.com/Never-mind/p/8032473.html
Copyright © 2011-2022 走看看