• [最小费用流]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);
    }
    

      

  • 相关阅读:
    socket编程原理
    配置Symbian WINS Emulator
    mysql 的乱码解决方法
    深入剖析关于JSP和Servlet对中文的处理
    一个分众传媒业务员的销售日记
    中移动第四季度SP评级结果出炉 A级企业仅5家
    基于socket的聊天室实现原理
    看Linux内核源码 练内力必备技能
    Dell要收购AMD?
    同步执行其他程序(dos命令)
  • 原文地址:https://www.cnblogs.com/kgs719/p/9804835.html
Copyright © 2020-2023  润新知