购物问题 |
难度级别:C; 运行时间限制:1000ms; 运行空间限制:51200KB; 代码长度限制:2000000B |
试题描述
|
由于换季,ACM商场推出优惠活动,以超低价格出售若干种商品。但是,商场为避免过分亏本,规定某些商品不能同时购买,而且每种超低价商品只能买一件。身为顾客的你想获得最大的实惠,也就是争取节省最多的钱。经过仔细研究过,我们发现,商场出售的超低价商品中,不存在以下这种情况:N(3<=n)种商品C1,C2,…,Cn,其中Ci和Ci+1是不能同时购买的(i=1,2,…,n-1),而且C1和Cn也不能同时购买。请编程计算可以节省的最大金额数。
|
输入
|
第1行两个整数K,M(1<=k<=1000),其中K表示超低价商品数,K种商品的编号依次为1,2,…,K;M表示不能同时购买的商品对数。接下来K行,第i行有一个整数Xi表示购买编号为i的商品可以节省的金额(1<=Xi<=100)。再接下来M行,每行两个数A和B,表示A和B不能同时购买,1<=A<=K,1<=B<=K,A≠B。
|
输出
|
仅一个整数,表示能节省的最大金额数。
|
输入示例
|
3 1
1 1 1 1 2 |
输出示例
|
2
|
其他说明
|
ssf校内训练
|
题解:好水的题,赤裸裸的二分图。。。(虽然本意是想考DP吧。。。但我们有高级货啊。。。= =)
二分图补集转换的思想不唠叨了,别忘了最大流建模的时候上两条边最后再除以二。
跟501一样瞎搞就好了= =
同时,这次“惨痛”的教训告诉我们,抄最大流模板的时候记得改addedge,我太傻了...
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar(' ') 9 using namespace std; 10 const int maxn=100000+10,maxm=2000000+10,inf=-1u>>1; 11 struct ISAP{ 12 struct tedge{int x,y,w,next;}adj[maxm];int ms,fch[maxn]; 13 int gap[maxn],s[maxn],cur[maxn],d[maxn],S,T,top,n; 14 void init(int n){ 15 this->n=n;ms=0;top=0; 16 memset(fch,-1,sizeof(fch)); 17 memset(d,-1,sizeof(d)); 18 return; 19 } 20 void addedge(int u,int v,int w){ 21 adj[ms]=(tedge){u,v,w,fch[u]};fch[u]=ms++; 22 adj[ms]=(tedge){v,u,0,fch[v]};fch[v]=ms++; 23 return; 24 } 25 void bfs(){ 26 queue<int>Q;Q.push(T);d[T]=0; 27 while(!Q.empty()){ 28 int u=Q.front();Q.pop(); 29 for(int i=fch[u];i!=-1;i=adj[i].next){ 30 int v=adj[i].y; 31 if(d[v]==-1) d[v]=d[u]+1,Q.push(v); 32 } 33 } return; 34 } 35 int maxflow(int S,int T){ 36 this->S=S;this->T=T;bfs();int k=S,i,flow=0; 37 for(i=1;i<=n;i++) cur[i]=fch[i],gap[d[i]]++; 38 while(d[S]<n){ 39 if(k==T){ 40 int mi=inf,pos; 41 for(i=0;i<top;i++) if(adj[s[i]].w<mi) mi=adj[s[i]].w,pos=i; 42 for(i=0;i<top;i++) adj[s[i]].w-=mi,adj[s[i]^1].w+=mi; 43 flow+=mi;top=pos;k=adj[s[top]].x; 44 } 45 for(i=cur[k];i!=-1;i=adj[i].next){ 46 int v=adj[i].y; 47 if(adj[i].w&&d[k]==d[v]+1){cur[k]=i;k=v;s[top++]=i;break;} 48 } 49 if(i==-1){ 50 int lim=n; 51 for(i=fch[k];i!=-1;i=adj[i].next){ 52 int v=adj[i].y; 53 if(adj[i].w&&d[v]<lim) lim=d[v],cur[k]=i; 54 } if(--gap[d[k]]==0) break; 55 d[k]=lim+1;gap[d[k]]++; 56 if(k!=S) k=adj[s[--top]].x; 57 } 58 } return flow; 59 } 60 }sol; 61 inline int read(){ 62 int x=0,sig=1;char ch=getchar(); 63 while(!isdigit(ch)){if(ch=='-') sig=-1;ch=getchar();} 64 while(isdigit(ch)) x=10*x+ch-'0',ch=getchar(); 65 return x*=sig; 66 } 67 inline void write(int x){ 68 if(x==0){putchar('0');return;}if(x<0) putchar('-'),x=-x; 69 int len=0,buf[15];while(x) buf[len++]=x%10,x/=10; 70 for(int i=len-1;i>=0;i--) putchar(buf[i]+'0');return; 71 } 72 void init(){ 73 int n=read(),m=read();sol.init((n<<1)+3); 74 int S=(n<<1)+1,T=(n<<1)+2,tot=0; 75 for(int i=1;i<=n;i++){ 76 int cur=read();tot+=cur; 77 sol.addedge(S,i,cur); 78 sol.addedge(i+n,T,cur); 79 } 80 while(m--){ 81 int x=read(),y=read(); 82 sol.addedge(x,y+n,inf); 83 sol.addedge(y,x+n,inf); 84 } 85 write(tot-(sol.maxflow(S,T)>>1)); 86 return; 87 } 88 89 void work(){ 90 return; 91 } 92 void print(){ 93 return; 94 } 95 int main(){ 96 init();work();print();return 0; 97 }