zoukankan      html  css  js  c++  java
  • 4253. 【五校联考7day2】QYQ在艾泽拉斯

    Description&Data Constraint

    在艾泽拉斯的无尽之海里,有着一群不为人知的由各个种族的冒险者统治的岛屿,这些岛屿都很庞大,足以在上面建造许多的城市,城市之间有一些单向道路连接。

    有一天,QYQ无意中发现了这些岛屿,并且发现在每个城市的地下都或多或少埋藏着一些装备、金币、宝物……
    可是正当QYQ兴奋不已打算全部把它们拿走时,他却惊奇的发现你的魔法在这里被限制住了,唯一可用的技能就是闪现,而且魔法只够他使用 (K) 次这个技能了,每次使用这个技能QYQ只能从一个岛屿上闪现到另外一个岛屿上。每一个岛屿只能登上一次,QYQ可以从任何一个城市开始旅程,在任何一个城市结束旅程。

    城市的数量共有 (n) 个,有 (m) 条道路,每一条道路有两个参数(u,v),表示从 (u)(v) 有一条道路,但你只能由 (u)(v) 走,两个城市属于相同的岛屿当且仅当暂时将所有道路视为双向道路时可以从其中一个城市走到另一个城市(可以途径其它城市)。
    每一个城市都有一个宝物的总价值 (v_i),你的任务是帮助QYQ得到最大总价值的宝物,并输出这个值。

    (1le nle10^6,1le mle10^7,1le v_ile10^3,0le Kle 10^6)

    Solution

    给出一个有向图,在边无视方向时的连通块被认为是一个岛屿,每个点有点权,然后在每个岛屿上按照方向求出最大价值,问前 (K) 大的岛屿的总价值之和。

    考虑先 ( ext{tarjan})​​ 缩环,求出每个 ( ext{DAG})​​。然后对于每个 ( ext{DAG})​​,拓扑排序+ ( ext{dp}) ​​求出最大价值和,最后排序即可。

    Code

    #include<stack>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define N 100005
    using namespace std;
    struct node
    {
    	int to,next;
    }a[N*20];
    stack<int> s;
    queue<int> q;
    int n,m,k,tot,col,cnt,res,w[N],head[N],x[N*10],y[N*10],fa[N],size[N],dfn[N],low[N],ans[N],f[N],rin[N],c[N],v[N];
    bool b[N],ins[N];
    void add(int x,int y)
    {
    	a[++tot].to=y;
    	a[tot].next=head[x];
    	head[x]=tot;
    }
    void tarjan(int x)
    {
    	dfn[x]=low[x]=++cnt;
    	s.push(x);
    	ins[x]=b[x]=true;
    	for (int i=head[x];i;i=a[i].next)
    	{
    		int v=a[i].to;
    		if (!b[v])
    		{
    			tarjan(v);
    			low[x]=min(low[x],low[v]);
    		}
    		else if (ins[v]) low[x]=min(low[x],low[v]);
    	}
    	if (dfn[x]==low[x])
    	{
    		++col;
    		int h=s.top();s.pop();
    		ins[h]=false;c[h]=col;v[col]+=w[h];
    		while (x!=h)
    		{
    			h=s.top();s.pop();
    			ins[h]=false;c[h]=col;v[col]+=w[h];
    		}
    	}
    }
    int find(int x)
    {
    	if (fa[x]!=x) fa[x]=find(fa[x]);
    	return fa[x];
    }
    int main()
    {
    	freopen("azeroth.in","r",stdin);
    	freopen("azeroth.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=m;++i)
    	{
    		scanf("%d%d",&x[i],&y[i]);
    		add(x[i],y[i]);
    	}
    	for (int i=1;i<=n;++i)
    		scanf("%d",&w[i]);
    	scanf("%d",&k);
    	for (int i=1;i<=n;++i)
    		if (!b[i]) tarjan(i);
    	tot=0;
    	memset(head,0,sizeof(head));
    	for (int i=1;i<=col;++i)
    		fa[i]=i,size[i]=1;
    	for (int i=1;i<=m;++i)
    		if (c[x[i]]!=c[y[i]])
    		{
    			add(c[x[i]],c[y[i]]);
    			++rin[c[y[i]]];
    			int X=find(c[x[i]]),Y=find(c[y[i]]);
    			if (X!=Y)
    			{
    				if (size[X]<size[Y]) fa[X]=Y,size[Y]+=size[X];
    				else fa[Y]=X,size[X]+=size[Y];
    			}
    		}
    	memset(b,false,sizeof(b));
    	for (int i=1;i<=col;++i)
    		if (!rin[i]) q.push(i);
    	while (!q.empty())
    	{
    		int h=q.front();q.pop();
    		f[h]+=v[h];
    		ans[find(h)]=max(ans[find(h)],f[h]);
    		for (int i=head[h];i;i=a[i].next)
    		{
    			int t=a[i].to;
    			--rin[t];
    			f[t]=max(f[t],f[h]);
    			if (!rin[t]) q.push(t);
    		}
    	}
    	sort(ans+1,ans+col+1);
    	for (int i=col;i>=col-k;--i)
    		res+=ans[i];
    	printf("%d
    ",res);
    	return 0;
    } 
    
  • 相关阅读:
    Incorrect integer value: '' for column 'id' at row 1 错误解决办法
    DT6.0关于SQL注入漏洞修复问题
    DT6.0框架留言模块漏洞修复
    Centos7 Rsync怎么实现热备份笔记
    撰写一篇博客要求讲述四则运算2的设计思想,源程序代码、运行结果截图、编程总结分析,并按照PSP0级的要求记录开发过程中的时间记录日志。
    软件工程概论——课程导入界面以及数据导入数据库
    软件工程概论 第一课:课后作业1
    完成课件中的动手动脑的或需要验证的相关内容。 (截止时间2017-11-16晚23:00)
    完成课件中的动手动脑的或需要验证的相关内容。
    课后作业:动手动脑之String.equals()方法、整理String类的Length()、charAt()、 getChars()、replace()、 toUpperCase()、 toLowerCase()、trim()、toCharArray()使用说明、阅读笔记发表到博客园。
  • 原文地址:https://www.cnblogs.com/Livingston/p/15119429.html
Copyright © 2011-2022 走看看