zoukankan      html  css  js  c++  java
  • bzoj2324 [ZJOI2011]营救皮卡丘

    上下界最小费用可行流,有tm重边,真傻逼

    就是$$i->i':(1,inf,0)$$

    $$i'->j:(0,inf,w)$$

    $$S->0:(0,num,0)$$

    $$i'->T:(0,inf,0)$$

    然后智障的建图就好了。

    之后顺便看了看达哥的floyed总结,深刻理解了floyed。

    每一层k的循环就是更新i->j路径上经过不大于k的点的最短路(i,j可以大于k,但路径上其他点不行)。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<algorithm>
     5 #include<cmath>
     6 #include<queue>
     7 #define N 350
     8 #define inf 0x7fffffff
     9 using namespace std;
    10 int n,m,num,S,T,SS,TT;
    11 int e=2,head[N];
    12 struct edge{
    13     int u,v,f,w,next;
    14 }ed[N*N*4];
    15 void add(int u,int v,int f,int w){
    16     ed[e].u=u;ed[e].v=v;ed[e].f=f;ed[e].w=w;
    17     ed[e].next=head[u];head[u]=e++;
    18     ed[e].u=v;ed[e].v=u;ed[e].f=0;ed[e].w=-w;
    19     ed[e].next=head[v];head[v]=e++;
    20 }
    21 int dis[N],from[N];
    22 bool vis[N];
    23 bool spfa(){
    24     memset(dis,0x3f,sizeof dis);
    25     memset(from,0,sizeof from);
    26     memset(vis,0,sizeof vis);
    27     queue<int> q;
    28     q.push(S);dis[S]=0;
    29     while(!q.empty()){
    30         int x=q.front();q.pop();vis[x]=0;
    31         for(int i=head[x];i;i=ed[i].next){
    32             int v=ed[i].v;
    33             if(ed[i].f&&dis[v]>dis[x]+ed[i].w){
    34                 dis[v]=dis[x]+ed[i].w;from[v]=i;
    35                 if(!vis[v]){vis[v]=1;q.push(v);}
    36             }
    37         }
    38     }
    39     return from[T];
    40 }
    41 int work(){
    42     int ans=0;
    43     while(spfa()){
    44         int F=inf;
    45         for(int i=from[T];i;i=from[ed[i].u])
    46             F=min(F,ed[i].f);
    47         for(int i=from[T];i;i=from[ed[i].u])
    48             ans+=F*ed[i].w,ed[i].f-=F,ed[i^1].f+=F;
    49     }
    50     return ans;
    51 }
    52 int g[N][N];
    53 int main(){//i->i':(1,inf,0) i'->j:(0,inf,w) S->0:(0,num,0) i'->T:(0,inf,0)
    54     memset(g,0x3f,sizeof g);
    55     scanf("%d%d%d",&n,&m,&num);n++;
    56     S=2*n+1,T=S+1,SS=T+1,TT=SS+1;
    57     for(int i=1;i<=n;i++)g[i][i]=0;
    58     for(int i=1,u,v,w;i<=m;i++){
    59         scanf("%d%d%d",&u,&v,&w);u++;v++;
    60         g[u][v]=g[v][u]=min(g[u][v],w);
    61     }
    62     for(int k=1;k<=n;k++)
    63         for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)
    64             if((k<=i||k<=j)&&g[i][j]>g[i][k]+g[k][j])
    65                 g[i][j]=g[i][k]+g[k][j];
    66     for(int i=1;i<=n;i++){
    67         add(i,n+i,inf,0);add(n+i,T,inf,0);
    68         add(i,TT,1,0);add(SS,n+i,1,0);
    69         for(int j=i+1;j<=n;j++)add(n+i,j,inf,g[i][j]);
    70     }
    71     add(S,1,num,0);add(T,S,inf,0);
    72     swap(S,SS),swap(T,TT);
    73     printf("%d
    ",work());
    74     return 0;
    75 }
    View Code
  • 相关阅读:
    1055 The World's Richest (25 分)
    1048 Find Coins (25 分)散列
    经典多线程问题(三)-子线程与主线程的循环打印
    经典多线程问题(二)-生产者消费者问题
    源码分析 CurrentHashMap 1.8
    源码分析 CurrentHashMap 1.7
    源码分析 HashTable与CurrentHashMap1.7与currentHashMap1.8对比
    源码分析 HashMap 1.8
    源码分析 HashMap 1.7
    Linux复习(常用命令)
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8305898.html
Copyright © 2011-2022 走看看