zoukankan      html  css  js  c++  java
  • 动态加边

    做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
    ",(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
    ",ans);
    74     return 0;
    75 }
    76 
    View Code
  • 相关阅读:
    51nod 1117 聪明的木匠:哈夫曼树
    51nod 1010 只包含因子2 3 5的数
    51nod 2636 卡车加油
    51nod 2989 组合数
    51nod 2652 阶乘0的数量 V2
    51nod 1103 N的倍数
    51nod 2489 小b和灯泡
    51nod 1003 阶乘后面0的数量
    51nod 2122 分解质因数
    javascript中的setter和getter
  • 原文地址:https://www.cnblogs.com/Ngshily/p/5053183.html
Copyright © 2011-2022 走看看