Magic Potion(最大流,跑两遍网络流或者加一个中转点)
Magic Potion
从源点到英雄分别拉容量为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 }
源点连英雄容量为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 }
posted on 2018-11-19 22:03 Fighting_sh 阅读(294) 评论(0) 编辑 收藏 举报