(2016北京集训十四)【xsy1557】task
题解:
限制可以看成图状结构,每个任务的对物品数量的影响可以看成权值,只不过这个权值用一个五元组来表示。
那么题意要求的就是最大权闭合子图,网络流经典应用。
代码:
1 #include<algorithm>
2 #include<iostream>
3 #include<cstring>
4 #include<cstdio>
5 #include<cmath>
6 #include<queue>
7 #define inf 100000000000000000
8 using namespace std;
9 typedef long long ll;
10 struct edge{
11 int v,next;
12 ll w;
13 }a[100001];
14 int n,m,k,u,v,vs,vt,tot=1,dep[100001],anss[10],head[100001];
15 ll ans=0,tmp,sum=0,cnt=0;
16 char op[10];
17 queue<int>q;
18 void add(int u,int v,ll w){
19 a[++tot].v=v;
20 a[tot].w=w;
21 a[tot].next=head[u];
22 head[u]=tot;
23 }
24 bool bfs(){
25 memset(dep,0,sizeof(dep));
26 while(!q.empty())q.pop();
27 q.push(vs);
28 dep[vs]=1;
29 while(!q.empty()){
30 int u=q.front();
31 q.pop();
32 for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
33 int v=a[tmp].v;
34 if(!dep[v]&&a[tmp].w){
35 dep[v]=dep[u]+1;
36 if(v==vt)return true;
37 q.push(v);
38 }
39 }
40 }
41 return false;
42 }
43 ll dfs(int u,ll num){
44 if(u==vt||!num)return num;
45 ll ans=0;
46 for(int tmp=head[u];tmp!=-1;tmp=a[tmp].next){
47 int v=a[tmp].v;
48 ll w=a[tmp].w;
49 if(dep[v]==dep[u]+1&&w){
50 ll f=dfs(v,min(num,w));
51 if(f){
52 a[tmp].w-=f;
53 a[tmp^1].w+=f;
54 ans+=f;
55 num-=f;
56 if(!num)break;
57 }
58 }
59 }
60 if(num>0)dep[u]=-1;
61 return ans;
62 }
63 int main(){
64 memset(head,-1,sizeof(head));
65 scanf("%d%d%d",&n,&m,&k);
66 vs=n+1,vt=n+2;
67 for(int i=1;i<=k;i++)ans=ans*2001+1000;
68 for(int i=1;i<=n;i++){
69 scanf("%s",op+1);
70 tmp=0;
71 for(int j=1;j<=k;j++){
72 tmp*=2001;
73 if(op[j]=='+')tmp++;
74 if(op[j]=='-')tmp--;
75 }
76 if(tmp<0){
77 add(vs,i,-tmp);
78 add(i,vs,0);
79 }else{
80 sum+=tmp;
81 add(i,vt,tmp);
82 add(vt,i,0);
83 }
84 }
85 for(int i=1;i<=m;i++){
86 scanf("%d%d",&u,&v);
87 add(v,u,inf);
88 add(u,v,0);
89 }
90 while(bfs()){
91 cnt+=dfs(vs,inf);
92 }
93 ans-=cnt-sum;
94 for(int i=k;i;i--){
95 anss[i]=ans%2001;
96 ans/=2001;
97 }
98 for(int i=1;i<=k;i++)printf("%d ",anss[i]);
99 return 0;
100 }