CF 132E 费用流

题意:

题解:

今天又遇到这个类型的建图题,有没有做出来。

于是今天总结一下这个题的模型——顶点覆盖(每个顶点恰好覆盖一次)

先不考虑赋初值的费用:

考虑赋初值:

具体做法请参考:http://www.cnblogs.com/proverbs/archive/2013/01/06/2848043.html

尽管不是一道题目,但是其实思想是一样的,赋初值=瞬移

View Code
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <cstdlib>
  5 
  6 #define N 2000
  7 #define M 200000
  8 #define INF 1e9
  9 #define BUG system("pause")
 10 
 11 using namespace std;
 12 
 13 int head[N],next[M],to[M],len[M],pr[M];
 14 int dis[N],pre[N],q[M],mlen;
 15 int val[N],sp[N],sb[N];
 16 bool vis[N];
 17 int n,m,T,S,cnt,S1;
 18 
 19 inline void add(int u,int v,int r,int w)
 20 {
 21     to[cnt]=v; len[cnt]=r; pr[cnt]=w; next[cnt]=head[u]; head[u]=cnt++;
 22     to[cnt]=u; len[cnt]=0; pr[cnt]=-w; next[cnt]=head[v]; head[v]=cnt++;
 23 }
 24 
 25 inline int cal(int x)
 26 {
 27     int rt=0;
 28     while(x)
 29     {
 30         if(x&1) rt++;
 31         x>>=1;
 32     }
 33     return rt;
 34 }
 35 
 36 inline void read()
 37 {
 38     scanf("%d%d",&n,&m);
 39     for(int i=1;i<=n;i++)
 40     {
 41         scanf("%d",&sp[i]);
 42         val[i]=cal(sp[i]);
 43     }
 44     memset(head,-1,sizeof head); cnt=0;
 45     memset(vis,0,sizeof vis);
 46     S=0,S1=n+n+1; T=S1+1;
 47     add(S,S1,m,0);
 48     for(int i=1;i<=n;i++)
 49     {
 50         add(S1,i+n,1,val[i]);
 51         add(S,i,1,0);
 52         add(i+n,T,1,0);
 53     }
 54     for(int i=1;i<=n;i++)
 55         for(int j=i+1;j<=n;j++)
 56         {
 57             if(sp[j]!=sp[i]) add(i,j+n,1,val[j]);
 58             else add(i,j+n,1,0);
 59         }
 60 }
 61 
 62 inline bool spfa()
 63 {
 64     memset(pre,-1,sizeof pre);
 65     memset(dis,0x3f,sizeof dis);
 66     q[1]=S; vis[S]=true; dis[S]=0;
 67     int h=1,t=2,sta;
 68     while(h<t)
 69     {
 70         sta=q[h++]; vis[sta]=false;
 71         for(int i=head[sta];~i;i=next[i])
 72             if(len[i]&&dis[to[i]]>dis[sta]+pr[i])
 73             {
 74                 dis[to[i]]=dis[sta]+pr[i];
 75                 pre[to[i]]=i;
 76                 if(!vis[to[i]]) vis[to[i]]=true,q[t++]=to[i];
 77             }
 78     }
 79     return pre[T]!=-1;
 80 }
 81 
 82 inline void updata()
 83 {
 84     mlen=INF;
 85     for(int i=pre[T];~i;i=pre[to[i^1]])
 86         mlen=min(mlen,len[i]);
 87     for(int i=pre[T];~i;i=pre[to[i^1]])
 88         len[i]-=mlen,len[i^1]+=mlen;
 89 }
 90 
 91 inline void dfs(int u,int bh)
 92 {
 93     sb[u]=bh;
 94     for(int i=head[u];~i;i=next[i])
 95         if(!(i&1)&&!len[i]&&to[i]!=S)
 96         {
 97             if(pr[i]!=0) vis[to[i]-n]=true;
 98             dfs(to[i]-n,bh);
 99         }
100 }
101 
102 inline void go()
103 {
104     int ans=0,h=0,num=0;
105     while(spfa()) updata(),ans+=mlen*dis[T];
106     for(int i=head[S1];~i;i=next[i])
107         if(!(i&1)&&!len[i])
108         {
109             vis[to[i]-n]=true;
110             h++;
111             dfs(to[i]-n,h);
112         }
113     h=0;
114     for(int i=1;i<=n;i++)
115         if(vis[i]) h++;
116     printf("%d %d\n",h+n,ans);
117     for(int i=1;i<=n;i++)
118     {
119         if(vis[i]) printf("%c=%d\n",sb[i]+'a'-1,sp[i]);
120         printf("print(%c)\n",sb[i]+'a'-1);
121     }
122 }
123 
124 int main()
125 {
126     read();
127     go();
128     return 0;
129 }
原文地址:https://www.cnblogs.com/proverbs/p/2857814.html