[CSAcademy]Cycle Tree

[CSAcademy]Cycle Tree

题目大意:

定义环树是一张无向连通的简单图,它的生成方式如下:

  1. \(2\)个点\(1\)条边的图是环树;
  2. 对任意一个环树,加入\(k\)个点\(a_{1\sim k}\),加入方式为从原图中选择一条边\((u,v)\),连接\((u,a_1),(a_1,a_2)\ldots(a_{k-1},a_k),(a_k,v)\),得到的图也是环树。

给定一个\(n(n\le5\times10^4)\)个点,\(m(m\le10^5)\)条边的环树,求最大独立集大小。

思路:

每次选取一个度数为\(2\)的点,将这条边删掉,将相邻的两点间连上虚点。不断进行这样的操作,最后只会剩下\(2\)个点。

\(f[0/1][0/1][i][j]\)表示对于边\((i,j)\),是否选取\(i/j\)的最大独立集,按照删点的顺序进行DP即可。

每个点最多被删一次,因此时间复杂度\(\mathcal O(n+m)\)

源代码:

#include<map>
#include<set>
#include<queue>
#include<cstdio>
#include<cctype>
#include<climits>
inline int getint() {
	register char ch;
	while(!isdigit(ch=getchar()));
	register int x=ch^'0';
	while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
	return x;
}
const int N=5e4+1;
bool inq[N];
std::queue<int> q;
std::set<int> e[N],set[N];
std::map<int,int> f[2][2][N];
inline void add_edge(const int &u,const int &v) {
	e[u].emplace(v);
	e[v].emplace(u);
}
inline void add(int &x,const int &y) {
	x+=y;
}
inline void up(int &x,const int &y) {
	x=std::max(x,y);
}
int main() {
	const int n=getint(),m=getint();
	for(register int i=0;i<m;i++) {
		const int u=getint(),v=getint();
		add_edge(u,v);
		f[0][0][u][v]=f[0][0][v][u]=0;
		f[0][1][u][v]=f[1][0][v][u]=1;
		f[1][0][u][v]=f[0][1][v][u]=1;
		f[1][1][u][v]=f[1][1][v][u]=INT_MIN;
		set[u].insert(v);
		set[v].insert(u);
	}
	int ans=1;
	for(register int i=1;i<=n;i++) {
		if(e[i].size()==2) {
			q.push(i);
			inq[i]=true;
		}
	}
	while(!q.empty()) {
		const int x=q.front();
		q.pop();
		if(e[x].size()!=2) continue;
		const int u=*e[x].begin(),v=*e[x].rbegin();
		add(f[0][0][u][v],std::max(f[0][0][x][u]+f[0][0][x][v],f[1][0][x][u]+f[1][0][x][v]-1));
		add(f[0][1][u][v],std::max(f[0][0][x][u]+f[0][1][x][v],f[1][0][x][u]+f[1][1][x][v]-1)-!!f[0][1][u][v]);
		add(f[1][0][u][v],std::max(f[0][1][x][u]+f[0][0][x][v],f[1][1][x][u]+f[1][0][x][v]-1)-!!f[1][0][u][v]);
		if(!set[u].count(v)) add(f[1][1][u][v],std::max(f[0][1][x][u]+f[0][1][x][v],f[1][1][x][u]+f[1][1][x][v]-1)-2*!!f[1][1][u][v]);
		up(ans,f[0][0][v][u]=f[0][0][u][v]);
		up(ans,f[1][0][v][u]=f[0][1][u][v]);
		up(ans,f[0][1][v][u]=f[1][0][u][v]);
		up(ans,f[1][1][v][u]=f[1][1][u][v]);
		e[x].clear();
		e[u].erase(x);
		e[v].erase(x);
		e[u].insert(v);
		e[v].insert(u);
		if(e[u].size()==2&&!inq[u]) {
			q.push(u);
			inq[u]=true;
		}
		if(e[v].size()==2&&!inq[v]) {
			q.push(v);
			inq[v]=true;
		}
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2018-09-05 14:21  skylee03  阅读(120)  评论(0编辑  收藏  举报