动态加边

做tsinsen发现题解都舔不懂QAQ,只能学习一个

  • bzoj1070修车

    吃了hzwer的安利,是为下一道题做铺垫

    n辆车,m个修车工,把修车工拆成n个,每辆车分别向n*m个修车工连边,第i辆车向第(j-1)*n+k个修车工连的边边权为t[i][j]*k,代表第j个修车工修的倒数第k辆车为i

    这样建边的意义在于,修车工修倒数第k辆车只会对他修的倒数第k辆车及这辆车以后的车的等待时间产生影响,影响恰为t[i][j]*k

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3  
 4 #define inf 0x3f3f3f3f
 5 #define maxn 605
 6 #define maxm 33005
 7 int cnt,v[maxm<<1],w[maxm<<1],c[maxm<<1],next[maxm<<1],first[maxn];
 8 int n,m,SSS,TTT,cost,dist[maxn],q[maxn],vis[maxn],tim[65][15];
 9  
10 void add(int st,int end,int val,int cst){
11     v[cnt]=end;w[cnt]=val;c[cnt]=cst;next[cnt]=first[st];first[st]=cnt++;
12     v[cnt]=st;w[cnt]=0;c[cnt]=-cst;next[cnt]=first[end];first[end]=cnt++;
13 }
14 bool spfa(){
15     int head=0,tail=0;
16     memset(dist,0x3f,sizeof(dist));
17     memset(vis,0,sizeof(vis));
18     q[tail++]=SSS;
19     vis[SSS]=1;
20     dist[SSS]=0;
21     int nn=TTT+1;
22     while(head!=tail){
23         int x=q[head];
24         if(++head==nn)head=0;
25         vis[x]=0;
26         for(int e=first[x];e!=-1;e=next[e])
27             if(w[e]&&dist[v[e]]>dist[x]+c[e]){
28                 dist[v[e]]=dist[x]+c[e];
29                 if(!vis[v[e]]){
30                     vis[v[e]]=1;
31                     q[tail]=v[e];
32                     if(++tail==nn)tail=0;
33                 }
34             }
35     }
36     return dist[TTT]!=inf;
37 }
38 int dfs(int x,int lim){
39     if(x==TTT)return lim;
40     int lim1=lim;
41     for(int e=first[x];e!=-1;e=next[e]){
42         if(!vis[v[e]]&&w[e]&&dist[v[e]]==dist[x]+c[e]){
43             vis[v[e]]=1;
44             int flow=dfs(v[e],min(lim,w[e]));
45             w[e]-=flow;w[e^1]+=flow;
46             cost+=c[e]*flow;
47             if((lim-=flow)<=0)break;
48         }
49     }
50     if(lim==lim1)dist[x]=inf;
51     return lim1-lim;
52 }
53 int main(){
54     memset(first,-1,sizeof(first));
55     scanf("%d%d",&m,&n);//n cars, m people
56     int tot=n*m;
57     SSS=0,TTT=tot+n+1;
58     for(int i=1;i<=n;i++)
59         for(int j=1;j<=m;j++)
60             scanf("%d",&tim[i][j]);
61     for(int i=1;i<=n;i++){
62         add(SSS,tot+i,1,0);
63         for(int j=1;j<=m;j++)
64             for(int k=1;k<=n;k++)
65                 add(i+tot,(j-1)*n+k,1,tim[i][j]*(n-k+1));
66     }
67     for(int i=1;i<=m;i++)
68         for(int j=1;j<=n;j++)
69             add((i-1)*n+j,TTT,1,0);
70     while(spfa()){
71         memset(vis,0,sizeof(vis));
72         vis[SSS]=1;
73         dfs(SSS,inf);
74     }
75     printf("%.2lf\n",(double)cost/n);//
76     return 0;
77 }
78 
View Code
  • bzoj2879美食节

    数据范围大得飞起来

    于是要先连一部分边,然后在每一次增广之后为增广的节点加边,使得在下一次增时保证所有厨师都在备选方案中

    通过这道题也发现之前写的重口味都是萎的,于是立下了以后再写重口味就cisi的flag

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3  
 4 #define inf 0x3f3f3f3f
 5 #define maxn 100005
 6 #define maxm 3000005
 7 int cnt,u[maxm<<1],v[maxm<<1],w[maxm<<1],c[maxm<<1],Next[maxm<<1],first[maxn];
 8 int ans,SSS,TTT,tot,haha,n,m,dist[maxn],q[maxn],p[45],pre[maxn],t[45][105],vis[maxn];
 9 void add(int st,int end,int val,int cst){
10     u[cnt]=st;v[cnt]=end;w[cnt]=val;c[cnt]=cst;Next[cnt]=first[st];first[st]=cnt++;
11     u[cnt]=end;v[cnt]=st;w[cnt]=0;c[cnt]=-cst;Next[cnt]=first[end];first[end]=cnt++;
12 }
13 bool spfa(){
14     int head=0,tail=0;
15     memset(dist,0x3f,sizeof(dist));
16     memset(vis,0,sizeof(vis));
17     q[tail++]=SSS;
18     dist[SSS]=0,vis[SSS]=1;
19     while(head!=tail){
20         int x=q[head];
21         if(++head==maxn)head=0;
22         vis[x]=0;
23         for(int e=first[x];e!=-1;e=Next[e])
24             if(w[e]&&dist[v[e]]>dist[x]+c[e]){
25                 dist[v[e]]=dist[x]+c[e];
26                 pre[v[e]]=e;
27                 if(!vis[v[e]]){
28                     vis[v[e]]=1;
29                     q[tail]=v[e];
30                     if(++tail==maxn)tail=0;
31                 }
32             }
33              
34     }
35     return dist[TTT]!=inf;
36 }
37 void mcf(){
38     int x=TTT,flow=inf;
39     while(x!=SSS){
40         flow=min(flow,w[pre[x]]);
41         x=u[pre[x]];
42     }
43     x=TTT;
44     while(x!=SSS){
45         ans+=flow*c[pre[x]];
46         w[pre[x]]-=flow;w[pre[x]^1]+=flow;
47         x=u[pre[x]];
48     }
49     int num=u[pre[TTT]],a=(num-1)/tot+1,b=num%tot+1;
50     add((a-1)*tot+b,TTT,1,0);
51     for(int i=1;i<=n;i++)
52         add(haha+i,(a-1)*tot+b,1,t[i][a]*b);
53 }
54 int main(){
55     memset(first,-1,sizeof(first));
56     scanf("%d%d",&n,&m);
57     SSS=0,TTT=maxn-1;
58     for(int i=1;i<=n;i++){
59         scanf("%d",&p[i]);
60         tot+=p[i];
61     }
62     haha=tot*m;
63     for(int i=1;i<=n;i++)
64         add(SSS,haha+i,p[i],0);
65     for(int i=1;i<=n;i++)
66         for(int j=1;j<=m;j++){
67             scanf("%d",&t[i][j]);
68             add(haha+i,(j-1)*tot+1,1,t[i][j]);
69         }
70     for(int i=1;i<=m;i++)
71         add((i-1)*tot+1,TTT,1,0);
72     while(spfa())mcf();
73     printf("%d\n",ans);
74     return 0;
75 }
76 
View Code

 

posted @ 2015-12-17 10:10  Ngshily  阅读(235)  评论(0编辑  收藏  举报