• [CSAcademy]Cycle Tree


    [CSAcademy]Cycle Tree

    题目大意:

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

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

    给定一个(n(nle5 imes10^4))个点,(m(mle10^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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    商贸通帐套隐藏方法
    固定资产打开提示:上年度数据未结转!
    ZOJ 2432 Greatest Common Increasing Subsequence
    POJ 1080 Human Gene Functions
    POJ 1088 滑雪
    POJ 1141 Brackets Sequence
    POJ 1050 To the Max
    HDOJ 1029 Ignatius and the Princess IV
    POJ 2247 Humble Numbers
    HDOJ 1181 变形课
  • 原文地址:https://www.cnblogs.com/skylee03/p/9591849.html
Copyright © 2020-2023  润新知