• 动态加边


    做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
  • 相关阅读:
    一天摄入多少蛋白质比较合理?
    给函数添加元数据(python)
    反转链表(C++实现)
    删除链表的中间节点(C++实现)
    在双向链表中删除倒数第K个链表节点(C++实现)
    在单链表中删除倒数第K个节点(C++实现)
    二叉树的创建及遍历(递归和非递归C++实现)
    删除排序数组中的重复项(C++实现)
    打印两个有序链表的公共部分(C++实现)
    用一个栈实现另一个栈的排序(C++实现)
  • 原文地址:https://www.cnblogs.com/Ngshily/p/5053183.html
Copyright © 2020-2023  润新知