Wannafly camp Day1 A Birthday

题意

  在蛋糕上插n支蜡烛,并把蛋糕分为m个区域,第i根蜡烛只能插在第ai个区域或第bi个区域,在一个区域内同时摆放x支蜡烛就要花费x2的时间。

  问摆放时间的最小值。

  n,m<=50

 

题解

  很容易发现此题无法贪心,由于n和m非常小,考虑建图跑网络流。

  对于cost为参数的平方的题,可以采用拆成n个点,费用为1、3、5...具体建图为:源点向每个蛋糕连边,每个区域拆成n个点,向汇点连边,每个蛋糕向可以在的两个区域的所有点连边,第i条边的费用为2 * i - 1。跑最小费用最大流即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define N 5010
 5 #define inf 0x3f3f3f3f
 6 
 7 inline int read(){
 8     int x=0,f=1;char ch=getchar();
 9     while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
10     while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
11     return x*f;
12 }
13 
14 int n,m,s,t,h[N],num=1,cost=0,price=0,mxflow=0;
15 bool vis[N];
16 struct edge{
17     int to,next,w,c;
18 }data[50010<<1];
19 inline void add(int x,int y,int w,int c){
20     data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].w=w;data[num].c=c;
21     data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].w=0;data[num].c=-c;
22 }
23 inline int dinic(int x,int low){
24     vis[x]=1;if(x==t){cost+=low*price;mxflow+=low;return low;}int tmp=low;
25     for(int i=h[x];i;i=data[i].next){
26         int y=data[i].to;if(vis[y]||!data[i].w||data[i].c) continue;
27         int res=dinic(y,min(tmp,data[i].w));
28         tmp-=res;data[i].w-=res;data[i^1].w+=res;
29         if(!tmp) return low;
30     }return low-tmp;
31 }
32 inline bool label(){
33     int d=inf;
34     for(int x=1;x<=n;++x){
35         if(!vis[x]) continue;
36         for(int i=h[x];i;i=data[i].next){
37             int y=data[i].to;if(vis[y]) continue;
38             if(data[i].w&&data[i].c<d) d=data[i].c;
39         }
40     }if(d==inf) return 0;
41     for(int x=1;x<=n;++x){
42         if(!vis[x]) continue;
43         for(int i=h[x];i;i=data[i].next)
44             data[i].c-=d,data[i^1].c+=d;
45     }price+=d;return 1;
46 }
47 
48 void mcmf()
49 {
50     do 
51         do
52             memset(vis,0,sizeof(vis));
53         while(dinic(s,inf));
54     while(label());
55 }
56 
57 int main()
58 {
59     n = read();
60     m = read();
61     s = 1;
62     t = n + n * m + 2;
63     for (int j = 2; j <= n + 1; ++j)
64     {
65         int a = read(), b = read();
66         add(s, j, 1, 0);
67         for (int i = 1; i <= n; ++i)
68         {
69             add(j, n + (a - 1) * n + i + 1, 1, 2 * i - 1);
70             add(j, n + (b - 1) * n + i + 1, 1, 2 * i - 1);
71         }
72     }
73     for (int i = n + 2; i < t; ++i)
74         add(i, t, 1, 0);
75     n = n + n * m + 2;
76     mcmf();
77     printf("%d\n", cost);
78 
79     return 0;
80 }

 

posted @ 2018-08-11 14:22  Aseer  阅读(216)  评论(0编辑  收藏  举报