【E - 食物链】

思路:

  • 基础种类并查集,注意取余+3
  • 读到文件尾会 WA,真是

总结:

  • 逻辑判断类题,当同属于同一集合(头元素相同)时进行判断;不属于同一集合时,合并。

代码:

  • 282ms 1116kB
//282ms		1116kB


#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 50005;

int N,K;
int ans;
int par[maxn];
int val[maxn];

void INIT(){
	ans = 0;
	memset(par , -1 , sizeof(par)) ;
	memset(val , 0  , sizeof(val)) ;
	return ;
}

int FIND(int i){
	if(par[i] == -1)
		return i;
	int temp = par[i];
	par[i] = FIND(par[i]);
	val[i] = (val[temp] + val[i])%3;
	return par[i];
}

void UNION(int w,int l,int r,int parl,int parr){
	par[parr] = parl;
	val[parr] = (val[l] + w - val[r] + 3) % 3;
	return ;
}

int main(){
	cin>>N>>K;
	INIT();
	while(K--){
		int type ;
		int l , r;
		scanf("%d%d%d" , &type , &l , &r);
		if(l>N || r>N || l<1 || r<1 || (type == 2 && l == r)){
			ans++ ;
			continue;
		}
		int parl = FIND(l);
		int parr = FIND(r);
		if(type == 1){
			if(parr == parl)
				if(val[l] != val[r])
					ans++;
				else	 ;
			else
				UNION(0 , l , r , parl , parr);
		}
		else{
			if(parr == parl)
				if((val[l] + 1)%3 != val[r])
					ans++;
				else	 ;
			else
				UNION(1 , l , r , parl , parr);
		}
	}
	cout<<ans<<endl;
	return 0;
}
### P4017 最大食物链计数问题的解决方案 对于最大食物链计数问题,可以采用图论中的拓扑排序以及动态规划相结合的方法来求解。该方法能够有效地处理有向无环图(DAG),并计算最长路径。 #### 方法概述 通过构建邻接表表示的食物网关系图,并利用入度数组记录每个节点的前驱数量。随后执行Kahn算法进行拓扑排序,在此过程中维护一个dp[]数组用于存储到达当前顶点的最大长度。最终遍历所有可能终点得到全局最优解。 #### 算法描述 - 初始化阶段:读取输入数据建立边集E和相应的邻接表G;初始化入度indegree[]为零。 - 构建过程:根据题目给定条件更新每条边对应的起点与终点之间的连接情况,同时增加相应结点的入度值。 - Kahn算法实施:创建队列Q保存所有入度为0的源点作为起始位置;当队列不为空时循环取出首元素u,尝试访问其相邻的所有v节点,如果发现某个被指向的位置满足入度减至0,则将其加入到待处理集合中继续扩展搜索空间。 - 动态转移方程定义:设f[i]代表以第i个物种结尾所能形成的食物链条数目总和,那么状态转换表达式可写作`f[v]=max{f[u]+1}`其中(u,v)属于已知存在的捕食者—猎物关联对。 - 结果汇总:统计整个生态系统内任意生物种群所参与构成的有效营养级联规模峰值即为目标函数输出结果。 下面是具体的Java代码实现: ```java import java.util.*; public class Main { static final int MAXN = 100005; static List<Integer>[] adjList = new ArrayList[MAXN]; static int[] indegree = new int[MAXN], dp = new int[MAXN]; public static void main(String[] args) { Scanner sc = new Scanner(System.in); // Read input data and initialize graph structure int n = sc.nextInt(), m = sc.nextInt(); for (int i = 0; i < n + 1; ++i) adjList[i] = new ArrayList<>(); while (--m >= 0){ int u = sc.nextInt(), v = sc.nextInt(); adjList[u].add(v); indegree[v]++; } Queue<Integer> q = new LinkedList<>(); for(int i=1;i<=n;++i) if(indegree[i]==0)q.offer(i); int ans = 0; while (!q.isEmpty()) { Integer curNode = q.poll(); for(Integer next : adjList[curNode]){ dp[next] = Math.max(dp[next], dp[curNode] + 1); --indegree[next]; if (indegree[next] == 0) q.add(next); ans = Math.max(ans, dp[next]); } } System.out.println(ans+1); // Add one because we count edges instead of nodes. } } ``` 上述程序实现了基于DAG上的最优化策略,适用于解决此类具有层次结构特征的问题实例[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值