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;
    } 
    
  • 相关阅读:
    php7垃圾回收机制
    PHP-FPM
    go main.main之前的准备
    ElementUI MessageBox 弹框
    ElementUI table 样式修改
    ElementUI Dropdown 下拉菜单
    vue+django实现下载文件
    ElementUI 点击展开/隐藏
    vue+django实现websocket连接
    ElementUI 上传文件以及限制
  • 原文地址:https://www.cnblogs.com/Livingston/p/15119429.html
Copyright © 2011-2022 走看看