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 }
没有人能阻止我前进的步伐,除了我自己!