zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    LLVM 0: LLVM和Clang的背景
    semaphore和mutex的区别?
    Note: TWLKH: 浅谈Semaphore与mutex
    Bark:自建 iOS 消息推送服务
    aka.ms打不开
    《UNIX 传奇:历史与回忆》Note
    crawlab 实现批量添加爬虫的功能
    手机浏览器打开PC端网站,背景显示不全怎么办?
    jquery实现平滑的二级下拉菜单效果
    nginx服务器设置301重定向,不带www跳转到带www域名
  • 原文地址:https://www.cnblogs.com/skylee03/p/9591849.html
Copyright © 2011-2022 走看看