bzoj5421:收藏家

bzoj5421

贴一张图

关于对问题的转化:

当两个人交换收藏品时,显然我们进行这个操作是为了得到更优解。

那么一个收藏品是有用的,另一个被换走的收藏品可以当做直接扔掉了。

所以只要保留一个就可以了。

注意边数、点数要开够

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 #define N 20010
 7 int min(int a,int b){return a<b?a:b;}
 8 int n,m,u,S,T,val[N],d[N],cur[N],fir[N]; bool vis[N];
 9 int cnt,hd[N],nxt[N<<1],ed[N],poi[N<<1];
10 int cap[N<<1],flow[N<<1],ans;
11 queue <int> h;
12 void adde(int x,int y,int v1,int v2){
13     nxt[ed[x]]=++cnt; hd[x]=hd[x]?hd[x]:cnt;
14     ed[x]=cnt; poi[cnt]=y; flow[cnt]=v1; cap[cnt]=v2;
15 }
16 #define to poi[i]
17 bool bfs(){
18     memset(vis,0,sizeof(vis));
19     h.push(S); vis[S]=1; d[S]=0;
20     while(!h.empty()){
21         int x=h.front(); h.pop();
22         for(int i=hd[x];i;i=nxt[i])
23             if(!vis[to]&&cap[i]>flow[i]){
24                 vis[to]=1; d[to]=d[x]+1;
25                 h.push(to);
26             }
27     }return vis[T];
28 }
29 int dinic(int x,int a){
30     if(!a||x==T) return a;
31     int F=0,f;
32     for(int &i=cur[x];i&&a;i=nxt[i])
33         if(d[to]==d[x]+1&&(f=dinic(to,min(a,cap[i]-flow[i])))>0){
34             F+=f; flow[i]+=f;
35             a-=f; flow[i^1]-=f;
36         }
37     return F;
38 }
39 void nect(int x,int y,int v){adde(x,y,0,v);adde(y,x,0,0);}//一条边以及它的反向边
40 int main(){
41     int TuT;scanf("%d",&TuT);
42     while(TuT--){
43         memset(hd,0,sizeof(hd));
44         memset(nxt,0,sizeof(nxt));
45         memset(ed,0,sizeof(ed));cnt=1;
46         scanf("%d%d",&n,&m);
47         S=1;T=u=2;ans=0;
48         for(int i=1;i<=n;++i){
49             scanf("%d",&val[i]);
50             nect(S,++u,1);fir[i]=u;
51         }
52         for(int i=1,q1,q2;i<=m;++i){
53             scanf("%d%d",&q1,&q2);
54             nect(fir[q1],++u,val[q1]);fir[q1]=u;
55             nect(fir[q2],++u,val[q2]);fir[q2]=u;
56             nect(fir[q1],fir[q2],1);
57             nect(fir[q2],fir[q1],1);
58         }nect(fir[1],T,val[1]);
59         while(bfs()){//普通dinic
60             for(int i=1;i<=u;++i) cur[i]=hd[i];
61             ans+=dinic(S,2e9);
62         }printf("%d\n",ans);
63     }return 0;
64 }
View Code

 

posted @ 2018-12-22 16:21  kafuuchino  阅读(208)  评论(0编辑  收藏  举报