GDCPC2024

按照赛后写的顺序。

I

\(a_x\ge a_y+a_z\) 代表有两个必须的条件是 \(a_x>a_y\)\(a_x>a_z\),发现这虽然不是一种偏序,但是它仍然具有传递性,所以建一张 DAG 后 toposort。从最后的点开始依次确定值。时间复杂度 \(O(n+m)\)

#include<bits/stdc++.h>
#define int long long
#define pii std::pair<int,int>
#define fi first
#define se second

const int maxn=2e5+10;

std::vector<int>a[maxn],f[maxn];

int rd[maxn],topo[maxn],ans[maxn];

std::vector<pii>b[maxn];

int n,m;

bool topo_sort(){
	std::queue<int>q;
	int cnt=0;
	for(int i=1;i<=n;i++) fprintf(stderr,"rd[%lld]=%lld\n",i,rd[i]);
	for(int i=1;i<=n;i++) if(rd[i]==0) q.push(i),topo[++cnt]=i;
	while(q.size()){
		int x=q.front();
		q.pop();
		for(int v:f[x]) {
			rd[v]--;
			if(rd[v]==0){
				topo[++cnt]=v;
				q.push(v);
			}
		}
	}
	fprintf(stderr,"cnt=%lld\n",cnt);
	return cnt==n;
}

signed main(){
	std::cin>>n>>m;
	for(int i=1;i<=m;i++){
		int x,y,z;
		std::cin>>x>>y>>z;
		a[x].push_back(y);
		a[x].push_back(z);
		b[x].push_back({y,z});
		f[y].push_back(x);
		f[z].push_back(x);
		rd[x]+=2;
	}
	if(!topo_sort()){
		printf("-1");
		return 0;
	}
	fprintf(stderr,"topo_sort finish\n");
	int sum=0;
	for(int i=1;i<=n;i++){
		//solve for topo[i]
		int mx=1;
		for(pii q:b[topo[i]]){
			mx=std::max(mx,ans[q.fi]+ans[q.se]);
			fprintf(stderr,"ans[%lld]=%lld and ans[%lld]=%lld then mx=%lld\n",q.fi,ans[q.fi],q.se,ans[q.se],mx);
		}
		ans[topo[i]]=mx;
		sum+=mx;
		fprintf(stderr,"topo[%lld]=%lld and ans[topo[%lld]]=%lld\n",i,topo[i],i,ans[topo[i]]);
	}
	if(sum>(int)1e9) printf("-1");
	else printf("%lld",sum);
}

C

这应该可以用哈夫曼树做,但那样太麻烦了。

考虑一种类似树形 dp 的方法,从下向上考虑。对于每个点贪心处理一下即可。

posted @ 2024-05-30 13:36  BYR_KKK  阅读(30)  评论(0编辑  收藏  举报