zoukankan      html  css  js  c++  java
  • [CodeChef FEB14]Graph Challenge解题报告(求半支配点)

    题意

    给一张有向图,使得从1开始按某种顺序DFS,可以让每个点的标号等于其DFS序号。求每个点的半支配点。

    题解

    使用Lengauer Tarjan算法,对这一算法的描述和证明见我的上一篇博文:

    当然本题只需要求半支配点。
    首先按照适当顺序DFS,还原题目描述中所称的DFS生成树。然后直接套算法。
    代码如下,思路很简单。要点都写在注释中了。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    using namespace std;
    const int SIZEN=100010;
    void getint(int &x){
    	char c=0;
    	for(;c<'0'||c>'9';c=getchar());
    	for(x=0;'0'<=c&&c<='9';c=getchar()) x=x*10+c-'0';
    }
    int N,M,Q;
    vector<int> c[SIZEN],ct[SIZEN];
    int timer=0,fa[SIZEN];
    int ufs[SIZEN],best[SIZEN],sdom[SIZEN];
    int find(int x){//将x连接到路径最上端,并计算出一路上诸点的best 
    	if(x==ufs[x]) return x;
    	int y=find(ufs[x]);
    	if(sdom[best[ufs[x]]]<sdom[best[x]]){//注意ufs[x]≠y 
    		best[x]=best[ufs[x]];
    	}
    	return ufs[x]=y;
    }
    void Lengauer_Tarjan(void){
    	for(int i=1;i<=N;i++) ufs[i]=best[i]=sdom[i]=i;
    	for(int i=N;i>=1;i--){
    		for(int j=0;j<ct[i].size();j++){
    			/*对于<i的那些,find之后是它本身 
    			对于>i的那些,find之后得到了它到根的最优sdom
    			注意,对于第二种情况,u~v这一路上必然全大于i*/
    			int u=ct[i][j];
    			find(u);
    			sdom[i]=min(sdom[i],sdom[best[u]]);
    		}
    		ufs[i]=fa[i];
    	}
    }
    bool vis[SIZEN];
    void DFS(int x){
    	vis[x]=true;
    	timer++;
    	for(int i=0;i<c[x].size();i++){
    		int u=c[x][i];
    		if(!vis[u]&&u==timer+1){
    			fa[u]=x;
    			DFS(u);
    		}
    	}
    }
    int ans[SIZEN];
    void work(void){
    	timer=0;
    	memset(vis,0,sizeof(vis));
    	fa[1]=0;
    	DFS(1);
    	Lengauer_Tarjan();
    	memset(ans,0,sizeof(ans));
    	for(int i=2;i<=N;i++) ans[sdom[i]]++;
    	int x;
    	for(int i=1;i<=Q;i++){
    		getint(x);
    		printf("%d ",ans[x]);
    	}
    	printf("
    ");
    }
    void read(void){
    	getint(N);getint(M);getint(Q);
    	for(int i=1;i<=N;i++) c[i].clear(),ct[i].clear();
    	int a,b;
    	for(int i=1;i<=M;i++){
    		getint(a);
    		getint(b);
    		c[a].push_back(b);
    		ct[b].push_back(a);
    	}
    	for(int i=1;i<=N;i++) sort(c[i].begin(),c[i].end());
    }
    int main(void){
    	//freopen("input.in","r",stdin);
    	int T;getint(T);
    	while(T--){
    		read();
    		work();
    	}
    	return 0;
    }
    


  • 相关阅读:
    数组与列表访问某一列的方法不同
    python 切片
    mapreduce统计数据库中的单词个数
    Call From s150/192.168.109.150 to 0.0.0.0:10020 failed on connection exception:
    message from server: "Host 'XXXX' is not allowed to connect to this MySQL server"
    Hadoop格式化namenode
    构建FP-growth算法高效发现频繁项集
    TypeError: '
    矩阵与列表取出行(左开右闭)
    2.nohup和&后台运行,进程查看及终止
  • 原文地址:https://www.cnblogs.com/wmdcstdio/p/7554222.html
Copyright © 2011-2022 走看看