zoukankan      html  css  js  c++  java
  • Magic Potion(最大流,跑两遍网络流或者加一个中转点)

    Magic Potion

    http://codeforces.com/gym/101981/attachments/download/7891/20182019-acmicpc-asia-nanjing-regional-contest-en.pdf

     

    从源点到英雄分别拉容量为1和2的边,跑两遍网络流,判断两次的大小和k的大小

      1 #include<iostream>
      2 #include<cstring>
      3 #include<string>
      4 #include<cmath>
      5 #include<cstdio>
      6 #include<algorithm>
      7 #include<queue>
      8 #include<vector>
      9 #include<set>
     10 
     11 #define maxn 500005
     12 #define MAXN 500005
     13 #define mem(a,b) memset(a,b,sizeof(a))
     14 const int N=200005;
     15 const int M=200005;
     16 const int INF=0x3f3f3f3f;
     17 using namespace std;
     18 int n;
     19 struct Edge{
     20     int v,next;
     21     int cap,flow;
     22 }edge[MAXN*20];//注意这里要开的够大。。不然WA在这里真的想骂人。。问题是还不报RE。。
     23 int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];
     24 int cnt=0;//实际存储总边数
     25 void isap_init()
     26 {
     27     cnt=0;
     28     memset(pre,-1,sizeof(pre));
     29 }
     30 void isap_add(int u,int v,int w)//加边
     31 {
     32     edge[cnt].v=v;
     33     edge[cnt].cap=w;
     34     edge[cnt].flow=0;
     35     edge[cnt].next=pre[u];
     36     pre[u]=cnt++;
     37 }
     38 void add(int u,int v,int w){
     39     isap_add(u,v,w);
     40     isap_add(v,u,0);
     41 }
     42 bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里,但是好像是时间要长
     43 {
     44     memset(dep,-1,sizeof(dep));
     45     memset(gap,0,sizeof(gap));
     46     gap[0]=1;
     47     dep[t]=0;
     48     queue<int>q;
     49     while(!q.empty())
     50     q.pop();
     51     q.push(t);//从汇点开始反向建层次图
     52     while(!q.empty())
     53     {
     54         int u=q.front();
     55         q.pop();
     56         for(int i=pre[u];i!=-1;i=edge[i].next)
     57         {
     58             int v=edge[i].v;
     59             if(dep[v]==-1&&edge[i^1].cap>edge[i^1].flow)//注意是从汇点反向bfs,但应该判断正向弧的余量
     60             {
     61                 dep[v]=dep[u]+1;
     62                 gap[dep[v]]++;
     63                 q.push(v);
     64                 //if(v==sp)//感觉这两句优化加了一般没错,但是有的题可能会错,所以还是注释出来,到时候视情况而定
     65                 //break;
     66             }
     67         }
     68     }
     69     return dep[s]!=-1;
     70 }
     71 int isap(int s,int t)
     72 {
     73     if(!bfs(s,t))
     74     return 0;
     75     memcpy(cur,pre,sizeof(pre));
     76     //for(int i=1;i<=n;i++)
     77     //cout<<"cur "<<cur[i]<<endl;
     78     int u=s;
     79     path[u]=-1;
     80     int ans=0;
     81     while(dep[s]<n)//迭代寻找增广路,n为节点数
     82     {
     83         if(u==t)
     84         {
     85             int f=INF;
     86             for(int i=path[u];i!=-1;i=path[edge[i^1].v])//修改找到的增广路
     87                 f=min(f,edge[i].cap-edge[i].flow);
     88             for(int i=path[u];i!=-1;i=path[edge[i^1].v])
     89             {
     90                 edge[i].flow+=f;
     91                 edge[i^1].flow-=f;
     92             }
     93             ans+=f;
     94             u=s;
     95             continue;
     96         }
     97         bool flag=false;
     98         int v;
     99         for(int i=cur[u];i!=-1;i=edge[i].next)
    100         {
    101             v=edge[i].v;
    102             if(dep[v]+1==dep[u]&&edge[i].cap-edge[i].flow)
    103             {
    104                 cur[u]=path[v]=i;//当前弧优化
    105                 flag=true;
    106                 break;
    107             }
    108         }
    109         if(flag)
    110         {
    111             u=v;
    112             continue;
    113         }
    114         int x=n;
    115         if(!(--gap[dep[u]]))return ans;//gap优化
    116         for(int i=pre[u];i!=-1;i=edge[i].next)
    117         {
    118             if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x)
    119             {
    120                 x=dep[edge[i].v];
    121                 cur[u]=i;//常数优化
    122             }
    123         }
    124         dep[u]=x+1;
    125         gap[dep[u]]++;
    126         if(u!=s)//当前点没有增广路则后退一个点
    127         u=edge[path[u]^1].v;
    128      }
    129      return ans;
    130 }
    131 
    132 struct sair{
    133     int num;
    134     int mp[505];
    135 }mp[505];
    136 
    137 int main(){
    138     std::ios::sync_with_stdio(false);
    139     int m,s,t,k;
    140     cin>>n>>m>>k;
    141     int a,b,c;
    142     isap_init();
    143     s=0,t=n+m+1;
    144     for(int i=1;i<=n;i++) add(s,i,1);
    145     for(int i=1;i<=n;i++){
    146         cin>>mp[i].num;
    147         for(int j=1;j<=mp[i].num;j++){
    148             cin>>mp[i].mp[j];
    149             add(i,n+mp[i].mp[j],1);
    150         }
    151     }
    152     for(int i=1;i<=m;i++) add(n+i,t,1);
    153     int tmp=n;
    154     n=t+1;
    155     int ans1=isap(s,t);
    156 
    157     n=tmp;
    158     isap_init();
    159     for(int i=1;i<=n;i++) add(s,i,2);
    160     for(int i=1;i<=n;i++){
    161         for(int j=1;j<=mp[i].num;j++){
    162             add(i,n+mp[i].mp[j],1);
    163         }
    164     }
    165     for(int i=1;i<=m;i++) add(n+i,t,1);
    166     tmp=n;
    167     n=t+1;
    168     int ans2=isap(s,t);
    169     if(ans2-ans1<=k){
    170         cout<<ans2<<endl;
    171     }
    172     else{
    173         cout<<ans1+k<<endl;
    174     }
    175 }
    View Code

    源点连英雄容量为1,英雄连怪物容量为1,怪物连汇点容量为1

    源点连中转点容量为k,中转点连英雄容量为1

      1 #include<iostream>
      2 #include<cstring>
      3 #include<string>
      4 #include<cmath>
      5 #include<cstdio>
      6 #include<algorithm>
      7 #include<queue>
      8 #include<vector>
      9 #include<set>
     10 
     11 #define maxn 500005
     12 #define MAXN 500005
     13 #define mem(a,b) memset(a,b,sizeof(a))
     14 const int N=200005;
     15 const int M=200005;
     16 const int INF=0x3f3f3f3f;
     17 using namespace std;
     18 int n;
     19 struct Edge{
     20     int v,next;
     21     int cap,flow;
     22 }edge[MAXN*20];//注意这里要开的够大。。不然WA在这里真的想骂人。。问题是还不报RE。。
     23 int cur[MAXN],pre[MAXN],gap[MAXN],path[MAXN],dep[MAXN];
     24 int cnt=0;//实际存储总边数
     25 void isap_init()
     26 {
     27     cnt=0;
     28     memset(pre,-1,sizeof(pre));
     29 }
     30 void isap_add(int u,int v,int w)//加边
     31 {
     32     edge[cnt].v=v;
     33     edge[cnt].cap=w;
     34     edge[cnt].flow=0;
     35     edge[cnt].next=pre[u];
     36     pre[u]=cnt++;
     37 }
     38 void add(int u,int v,int w){
     39     isap_add(u,v,w);
     40     isap_add(v,u,0);
     41 }
     42 bool bfs(int s,int t)//其实这个bfs可以融合到下面的迭代里,但是好像是时间要长
     43 {
     44     memset(dep,-1,sizeof(dep));
     45     memset(gap,0,sizeof(gap));
     46     gap[0]=1;
     47     dep[t]=0;
     48     queue<int>q;
     49     while(!q.empty())
     50     q.pop();
     51     q.push(t);//从汇点开始反向建层次图
     52     while(!q.empty())
     53     {
     54         int u=q.front();
     55         q.pop();
     56         for(int i=pre[u];i!=-1;i=edge[i].next)
     57         {
     58             int v=edge[i].v;
     59             if(dep[v]==-1&&edge[i^1].cap>edge[i^1].flow)//注意是从汇点反向bfs,但应该判断正向弧的余量
     60             {
     61                 dep[v]=dep[u]+1;
     62                 gap[dep[v]]++;
     63                 q.push(v);
     64                 //if(v==sp)//感觉这两句优化加了一般没错,但是有的题可能会错,所以还是注释出来,到时候视情况而定
     65                 //break;
     66             }
     67         }
     68     }
     69     return dep[s]!=-1;
     70 }
     71 int isap(int s,int t)
     72 {
     73     if(!bfs(s,t))
     74     return 0;
     75     memcpy(cur,pre,sizeof(pre));
     76     //for(int i=1;i<=n;i++)
     77     //cout<<"cur "<<cur[i]<<endl;
     78     int u=s;
     79     path[u]=-1;
     80     int ans=0;
     81     while(dep[s]<=n)//迭代寻找增广路,n为节点数
     82     {
     83         if(u==t)
     84         {
     85             int f=INF;
     86             for(int i=path[u];i!=-1;i=path[edge[i^1].v])//修改找到的增广路
     87                 f=min(f,edge[i].cap-edge[i].flow);
     88             for(int i=path[u];i!=-1;i=path[edge[i^1].v])
     89             {
     90                 edge[i].flow+=f;
     91                 edge[i^1].flow-=f;
     92             }
     93             ans+=f;
     94             u=s;
     95             continue;
     96         }
     97         bool flag=false;
     98         int v;
     99         for(int i=cur[u];i!=-1;i=edge[i].next)
    100         {
    101             v=edge[i].v;
    102             if(dep[v]+1==dep[u]&&edge[i].cap-edge[i].flow)
    103             {
    104                 cur[u]=path[v]=i;//当前弧优化
    105                 flag=true;
    106                 break;
    107             }
    108         }
    109         if(flag)
    110         {
    111             u=v;
    112             continue;
    113         }
    114         int x=n;
    115         if(!(--gap[dep[u]]))return ans;//gap优化
    116         for(int i=pre[u];i!=-1;i=edge[i].next)
    117         {
    118             if(edge[i].cap-edge[i].flow&&dep[edge[i].v]<x)
    119             {
    120                 x=dep[edge[i].v];
    121                 cur[u]=i;//常数优化
    122             }
    123         }
    124         dep[u]=x+1;
    125         gap[dep[u]]++;
    126         if(u!=s)//当前点没有增广路则后退一个点
    127         u=edge[path[u]^1].v;
    128      }
    129      return ans;
    130 }
    131 
    132 struct sair{
    133     int num;
    134     int mp[505];
    135 }mp[505];
    136 
    137 int main(){
    138     std::ios::sync_with_stdio(false);
    139     int m,s,t,k;
    140     cin>>n>>m>>k;
    141     int a,b,c;
    142     isap_init();
    143     s=0,t=n+m+1;
    144     int ck=t+1;
    145     for(int i=1;i<=n;i++)
    146         add(s,i,1);
    147     add(s,ck,k);
    148     for(int i=1;i<=n;i++){
    149         cin>>a;
    150         for(int j=1;j<=a;j++){
    151             cin>>b;
    152             add(i,n+b,1);
    153         }
    154     }
    155     for(int i=1;i<=m;i++)
    156         add(n+i,t,1);
    157     for(int i=1;i<=n;i++){
    158         add(ck,i,1);
    159     }
    160     int tmp=n;
    161     n=ck+1;
    162     int ans=isap(s,t);
    163     cout<<ans<<endl;
    164 }
    View Code
  • 相关阅读:
    感想篇:4)越来越精简的机械设计
    标准结构篇:5)热(散热)设计
    标准结构篇:4)EMC电磁兼容
    标准结构篇:2)O型橡胶密封圈
    进阶篇:1)制造发展阶段与对设计的要求
    标准结构篇:1)选用标准化的结构
    高阶篇:8.2)注塑模具讨论要点(讨模评审)
    基础篇:2.1)设计的深度-最小特征
    高阶篇:8.3)塑胶件试模
    高阶篇:8)注射模具开模流程总章
  • 原文地址:https://www.cnblogs.com/Fighting-sh/p/9986094.html
Copyright © 2011-2022 走看看