2022/8/19 题解

出去体检了,所以光荣抱灵

P4578 [FJOI2018]所罗门王的宝藏

  • 点开标签一看:

    图论

    我:???

Solution

  • 设操作完之后第 \(i\) 行的操作使第 \(i\) 行增加了 \(x_i\),第 \(j\) 列的操作使第 \(j\) 列减少了 \(y_j\),那么对于第 \(i\) 行第 \(j\) 列就有 \(x_i-y_j=v_{i,j}\),由此构造差分约束系统即可,求解的存在性即判负环,可使用早就死了的 \(\mathtt{SPFA}\)

  • 当然也有不用图论的方法,详情见 \(cyffff\) 大佬的题解;

AC Spfa
#include<bits/stdc++.h>
using namespace std;

inline int read(){
	int s=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		s=s*10+int(ch-'0');
		ch=getchar();
	}
	return s*f;
}

const int N=1e5+10;

int T,st;
int n,m,k;
int head[N],ver[N<<1],edge[N<<1],nxt[N<<1],tot=0;

void add(int x,int y,int z){
	ver[++tot]=y,edge[tot]=z;
	nxt[tot]=head[x],head[x]=tot;
	return ;
}

bool ans;
int dist[N],ind[N];
bool vis[N];

void Spfa(){
	memset(dist,0x3f3f3f3f,sizeof(dist));
	memset(vis,0,sizeof(vis));
	memset(ind,0,sizeof(ind));
	dist[st]=0;
	queue<int>q;
	q.push(st),ind[st]=1;
	while(q.size()){
		int x=q.front();
		q.pop();
		vis[x]=0;
		for(int i=head[x];i;i=nxt[i]){
			if(dist[ver[i]]>dist[x]+edge[i]){
				if(ind[ver[i]]>=n+m){
					ans=0;
					return ;
				}
				dist[ver[i]]=dist[x]+edge[i];
				if(!vis[ver[i]]){
					++ind[ver[i]];
					vis[ver[i]]=1;
					q.push(ver[i]);
				}
			}
		}
	}
	return ;
}

int main(){
	T=read();
	while(T--){
		memset(head,0,sizeof(head));
		n=read(),m=read(),k=read();
		tot=0;
		st=n+m+1;
		for(int i=1;i<=n+m;++i)
			add(st,i,0);
		int u,v,w;
		for(int i=1;i<=k;++i){
			u=read(),v=read(),w=read();
			add(u,v+n,w);
			add(n+v,u,-w);
		}
		ans=1;
		Spfa();
		printf("%s\n",ans?"Yes":"No");
	}
	return 0;
}

B.P3698 [CQOI2017]小Q的棋盘

  • 又是贪心;

Solution

  • 观察样例后,可以发现答案和这棵树上的最长链有关;

  • 最终的贪心策略为走最长链,如果最长链走不完,就能走多少走多少;
    如果最长链能走完,步数还有剩余的话,每两步可以走一个新点;

AC code
#include<bits/stdc++.h>
using namespace std;

inline int read(){
	int s=0,f=1;
	char ch=getchar();
	while(!isdigit(ch)){
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(isdigit(ch)){
		s=s*10+int(ch-'0');
		ch=getchar();
	}
	return s*f;
}

const int N=1e5+10;

int v,n;
int head[N],ver[N<<1],nxt[N<<1],tot=0;
int ans=0;

void add(int x,int y){
	ver[++tot]=y;
	nxt[tot]=head[x],head[x]=tot;
	return ;
}

void dfs(int p,int f,int dep){
	ans=max(ans,dep);
	for(int i=head[p];i;i=nxt[i]){
		if(ver[i]==f) continue;
		dfs(ver[i],p,dep+1);
	}
	return ;
}

int main(){
	v=read(),n=read();
	int a,b;
	for(int i=1;i<v;++i){
		a=read(),b=read();
		add(a+1,b+1);
		add(b+1,a+1);
	}
	dfs(1,-1,1);
	if(n<ans) printf("%d",n+1);
	else printf("%d",min(v,ans+((n-ans+1)>>1)));
	return 0;
}

C.P4460 [CQOI2018]解锁屏幕

D.P4577 [FJOI2018]领导集团问题

posted @ 2022-08-19 18:19  Star_LIcsAy  阅读(62)  评论(0)    收藏  举报