列表

详情


NC22617. 小D的剑阵

描述

落霞明 月盈盈 
来复无言去不闻 
动离愁 几人空留 
任他夏去复立秋
千帆过 天尽头 
流光脉脉盼归舟 
舟短情却长 纵使天边各一方 
愿与君两相望 
叫ぶ獣—《夕山谣》
题目背景
灵剑派,九州大陆五大超品宗派之一,如今,灵剑山正面临着建派历史上最大的危机——抵御堕仙界三分之二兵力的攻击。
这几乎是一个不可能完成的任务,灵剑山的毁灭只是时间问题。
只是,九州虽大,但灵剑山人无路可退,他们的身后就是灵剑山!
作为万仙盟五绝之一,灵剑派存有许多古剑,这些古剑配合护山大阵一起使用,威力巨大,曾多次于危难中拯救灵剑山,是灵剑派建派几千年来的底牌。但如今作为剑阵组成的核心——灵剑早已和最开始不同,因此重新安排剑阵成为了当务之急,作为灵剑山大师兄,王小D,担负起了这个重新安排剑阵的任务。
题目描述
现在你有 n 把灵剑,其中选择第i把灵剑会得到的 w_i 攻击力。
于此同时,还有q个约束,每个约束形如:
x 和 y 表示两个物品的编号,如果同时选中可以获得额外 v_0 的攻击力, 同时不选可以获得额外 v_1 点攻击力,只选择一个则会扣除 v_2 的攻击力。
王小D想知道剑阵的最大攻击力。
九州大陆的未来,必有灵剑山的一笔!

输入描述

第一行两个整数 n, q ,n表示灵剑数量,q表示约束数量。

接下来一行,共 n 个整数,第 i 个整数表示 w_i

接下来 q 行,每行五个整数,表示一个约束。

输出描述

共一行,输出最大的攻击力。

示例1

输入:

5 2
4 2 6 6 2 
4 2 4 2 2
5 1 6 6 4

输出:

30

说明:

5把灵剑都选 ,获得4+2+6+6+2+4+6=30的攻击力

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 39ms, 内存消耗: 1248K, 提交时间: 2019-02-15 20:23:23

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 100000 // 鐐规暟n+2m
#define M 700000 // 杈规暟4n+14m
#define inf 0x3f3f3f3f
using namespace std;
struct KSD
{
	int v,len,next;
}e[M];
int head[N],cnt;
inline void add(int u,int v,int len)
{
	e[++cnt].v=v;
	e[cnt].len=len;
	e[cnt].next=head[u];
	head[u]=cnt;
}
inline void Add(int u,int v,int len)
{add(u,v,len),add(v,u,len);}
int s,t,d[N];
queue<int>q;
bool bfs()
{
	while(!q.empty())q.pop();
	memset(d,0,sizeof d);

	int i,u,v;
	q.push(s),d[s]=1;
	while(!q.empty())
	{
		u=q.front(),q.pop();
		for(i=head[u];i;i=e[i].next)
		{
			if(!d[v=e[i].v]&&e[i].len)
			{
				d[v]=d[u]+1;
				if(v==t)return 1;
				q.push(v);
			}
		}
	}
	return 0;
}
int dinic(int x,int flow)
{
	if(x==t)return flow;
	int remain=flow,i,v,k;
	for(i=head[x];i&&remain;i=e[i].next)
	{
		if(d[v=e[i].v]==d[x]+1&&e[i].len)
		{
			k=dinic(v,min(remain,e[i].len));
			if(!k)d[v]=0;
			e[i].len-=k,e[i^1].len+=k;
			remain-=k;
		}
	}
	return flow-remain;
}
int n,m,maxflow;
bool build()
{
	int i,j,k;
	int a,b,c;
	int u,v;

	scanf("%d%d",&n,&m);

	s=0,t=n+m*2+1,cnt=1;
	for(i=1;i<=n;i++)
	{
		scanf("%d",&b);a=0;
		maxflow+=a+b;
		Add(s,i,a),Add(i,t,b);
	}
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d%d%d",&u,&v,&a,&b,&c);
		maxflow+=a+b;
		Add(s,n+i*2-1,b),Add(n+i*2-1,u,b),Add(n+i*2-1,v,b);
		Add(t,n+i*2,a),Add(n+i*2,u,a),Add(n+i*2,v,a);
		Add(u,v,c);
	}
	return 0;
}
int main()
{
	

	if(build())return 0;
	while(bfs())maxflow-=dinic(s,inf);
	printf("%d\n",maxflow);

	fclose(stdin);
	fclose(stdout);
	return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 16ms, 内存消耗: 640K, 提交时间: 2020-03-14 16:10:39

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e3+10,M=1e6+10;
int s,t,n,q,h[N],res,val[N];
int head[N],nex[M],to[M],w[M],tot=1;
inline void ade(int a,int b,int c)
{
	to[++tot]=b;
	nex[tot]=head[a];
	w[tot]=c;
	head[a]=tot;
 } 
 inline void add(int a,int b,int c)
 {
 	ade(a,b,c);
 	ade(b,a,0);
 }
 inline int bfs()
 {
 	queue<int> q;
 	q.push(s);
 	memset(h,0,sizeof h);
 	h[s]=1;
 	while(q.size())
 	{
 		int u=q.front();
 		q.pop();
 		for(int i=head[u];i;i=nex[i])
 		{
 			if(w[i]&&!h[to[i]])
 			{
 				h[to[i]]=h[u]+1;
 				q.push(to[i]);
			 }
		 }
	 }
	 return h[t];
 }
 int dfs(int x,int f)
 {
 	if(x==t) return f;
 	int fl=0;
 	for(int i=head[x];i&&f;i=nex[i])
 	{
 		if(w[i]&&h[to[i]]==h[x]+1)
 		{
 			int mi=dfs(to[i],min(w[i],f));
 			w[i]-=mi,w[i^1]+=mi,fl+=mi,f-=mi;
		 }
	 }
	 if(!fl) h[x]=-1;
	 return fl;
 }
 inline int dinic()
 {
 	int res=0;
 	while(bfs()) res+=dfs(s,inf);
 	return res;
 }
 int main()
 {
 	cin>>n>>q;
 	t=n+1;
 	for(int i=1;i<=n;i++)
 	cin>>val[i],res+=val[i];
 	while(q--)
 	{
 		static int x,y,v0,v1,v2;
 		cin>>x>>y>>v0>>v1>>v2;
 		res+=v0;
 		res+=v1;
		 val[x]+=v0/2;
		 val[y]+=v0/2;
		 add(x,t,v1/2);
		 add(y,t,v1/2);
		 add(x,y,v2+(v0+v1)/2);
		 add(y,x,v2+(v0+v1)/2); 
	 }
	 for(int i=1;i<=n;i++) add(s,i,val[i]);
	 cout<<res-dinic()<<endl;
	 return 0;
 }

上一题