思路:首先我们想到可以对相互憎恶的俩个骑士连边,这样就得到了一个图,有多个连通块,并且每个连通块中最多只有一个环。如果每个连通块都是一颗树,那么这个问题就很简单~每个节点都是选或者不选。
idea1:我想可不可以把这个比树多一条边的图,变成一棵树来处理,那么就是要删掉环上的一条边。考虑删掉这条边(u,v)的影响是什么,影响是u,v两点可能同时被选,产生错误的答案。
我的解决办法是把边删了的同时,分三种情况,1.把v[u]变成0 2.把v[v]变成0 3.把v[u],v[v]都变成0;因为如果一个点都变成0那答案中一定不包涵这个点。因为去掉这个点答案不会变劣;
产生的问题:
1.因为要删边,我用的是set<int> G[maxn]。这样复杂度就多了一个log。而且分三种情况,所以常数就比较大。T的我人都傻了
2.用set存会比vector消耗更多的内存。MLE。。。
3.cin即使加了流同步还是比scanf慢。。。所以还是用scanf吧
4.用数组实现邻接表会比用vector快一些
解决办法:
看了题解里的代码,发现这条边其实不用删,只要把u当成根,把v当成根分别算就行了,这样常数就小了。并且存图可以直接用邻接表,只要把其中一条边特判掉剩下的就是一棵树了
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define maxn 1000010
#define ll long long
#define pii pair<ll,ll>
ll v[maxn];int vis[maxn];
ll dp[maxn][2];
int sta,en,E