zoukankan      html  css  js  c++  java
  • [最小费用流]CCPC-Wannafly Summer Camp A:Birthday

    恬恬的生日临近了。宇扬给她准备了一个蛋糕。

    正如往常一样,宇扬在蛋糕上插了n支蜡烛,并把蛋糕分为m个区域。因为某种原因,他必须把第i根蜡烛插在第ai个区域或第bi个区域。区域之间是不相交的。宇扬在一个区域内同时摆放x支蜡烛就要花费x2的时间。宇扬布置蛋糕所用的总时间是他在每个区域花的时间的和。

    输入

    第一行包含两个整数nm(1 ≤ n ≤ 50, 2 ≤ m ≤ 50)。

    接下来n行,每行两个整数aibi(1 ≤ aibi ≤ m)。

    输出

    一个整数表示答案.

    思路:

    看下去毫无思路以为是dp,后面发现是网络流

    把每一区域拆成50个点,再将可以该区域可以插的蜡烛分别与50个点连流量为1,费用依次为1,3,5,7......99((x+1)^2-x^2=2x+1)这样的话从该区域流出的费用刚好为流入该区域的蜡烛的数量的平方。然后源点连每一个蜡烛,流量为1,费用为0,区域的每一个点连汇点,流量为1,费用为0,然后跑费用流就行了。

    #include<bits/stdc++.h>
    using namespace std;
    const int inf=2147483647;//2^31-1
    const int INF=1061109567;//一般设为无穷大
    const int maxn = 1e5+5;
    struct node{
        int u;
        int v;
        int c;
        int w;
        int next;
    }edge[maxn];
    int n,m,sp,tp,ednum=0;
    int a[maxn];
    int b[maxn];
    int dis[maxn];
    int pre[maxn];
    int pos[maxn];
    int p[maxn];
    int head[maxn];
    bool vis[maxn];
    queue<int>que;
    void initialization()
    {
        memset(head,-1,sizeof(head));
        ednum=0;
    }
    void Insert(int u,int v,int c,int w)
    {
        edge[ednum].u=u;
        edge[ednum].v=v;
        edge[ednum].c=c;
        edge[ednum].w=w;
        edge[ednum].next=head[u];
        head[u]=ednum++;
    }
    
    bool spfa()
    {
        memset(vis,true,sizeof(vis));
        memset(dis,63,sizeof(dis));
        vis[sp]=false;
        dis[sp]=0;
        p[sp]=inf;
        que.push(sp);
        while(!que.empty())
        {
            int u=que.front();
            que.pop();
            vis[u]=true;
            for(int i=head[u];i!=-1;i=edge[i].next)
            {
                int v=edge[i].v;
                if(edge[i].c>0&&dis[v]>dis[u]+edge[i].w)
                {
                    dis[v]=dis[u]+edge[i].w;
                    pos[v]=u;
                    pre[v]=i;
                    p[v]=min(p[u],edge[i].c);
                    if(vis[v])
                    {
                        que.push(v);
                        vis[v]=false;
                    }
                }
            }
        }
        return dis[tp]<INF;
    }
    int flow()
    {
       int ans=0;
        while(spfa())
        {
            ans+=p[tp]*dis[tp];
          //  cout<<ans<<"    AAAAAAA"<<endl;
            for(int i=tp;i!=sp;i=pos[i])
            {
                edge[pre[i]].c-=p[tp];
                edge[pre[i]^1].c+=p[tp];
            }
        }
        return ans;
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        initialization();
        sp = 0;
        tp = 50*60;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&a[i],&b[i]);
            Insert(sp,i,1,0);
            Insert(i,sp,0,0);
        }
        for(int i = 1; i <= n; i++)
        {
            for(int j = 1; j <= 50; j++)
            {
              //  cout<<i<<"    SSS    "<<a[i]*50+j<<endl;
                Insert(i, a[i]*50+j, 1, 0);
    
                Insert(a[i]*50+j, i, 0, 0);
    
                Insert(i, b[i]*50+j, 1, 0);
    
                Insert(b[i]*50+j, i, 0, 0);
            }
        }
        int ind = 0;
        for(int i = 51;i<=2550;i++)
        {
            ind++;
            Insert(i, tp, 1, 2*ind-1);
            Insert(tp, i, 0, -2*ind+1);
          //  cout<<2*ind-1<<"  DDDD      "<<i<<endl;
            ind%=50;
        }
        int ans1 = flow();
        printf("%d
    ",ans1);
    }
    

      

  • 相关阅读:
    解决input获取焦点时底部菜单被顶上来问题
    JavaScript学习笔记
    JavaScript表单验证
    js 中{},[]中括号,大括号使用详解
    陀飞轮
    娱乐天空
    左右手
    软测 学习
    git 学习
    spring boot 学习
  • 原文地址:https://www.cnblogs.com/kgs719/p/9804835.html
Copyright © 2011-2022 走看看