• 【UVA11324】 The Largest Clique (Tarjan+topsort/记忆化搜索)


    UVA11324 The Largest Clique

    题目描述

    给你一张有向图 (G),求一个结点数最大的结点集,使得该结点集中的任意两个结点 (u)(v) 满足:要么 (u) 可以达 (v),要么 (v) 可以达 (u)(u,v)相互可达也行)。

    输入输出格式

    输入格式:

    第一行:测试数据组数(T),每组数据的格式如下:
    第一行为结点数 (n) 和边数 (m) ,结点编号 (1~n)
    以下(m)行每行两个整数 (u)(v) ,表示一条有向边 (u->v)

    输出格式:

    每组数据输出最大结点集的结点数

    输入输出样例

    输入样例#1:

    1
    5 5
    1 2
    2 3
    3 1
    4 1
    5 2
    

    输出样例#1:

    4
    

    题解

    首先,我们会想到(Tarjan)缩点,将缩成的点的(siz)大小当做点权。

    因为缩完点之后就会是一个(DAG),所以可以跑DP。

    这种题型有两种实现方式,(topsort)和记忆化搜索,代码中已注明。

    转移就是(dp[v]=max(dp[v],dp[u]+siz[v])).

    code:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cctype>
    #include<queue>
    #define R register
    #define ll long long
    #define N 1005
    #define M 50005
    using namespace std;
    template<typename T>inline void read(T &a){
    	char c=getchar();T x=0,f=1;
    	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
    	a=f*x;
    }
    int T,n,m,u[M],v[M],ru[N],siz[N],h[N],sta[N],low[N],dfn[N];
    int top,num,tot,col[M],vis[N],dp[N],ans,cnt;
    struct node{
    	int nex,to;
    }edge[M];
    inline void add(R int u,R int v){
    	edge[++tot].nex=h[u];
    	edge[tot].to=v;
    	h[u]=tot;
    }
    inline void Tarjan(R int x){
    	dfn[x]=low[x]=++num;
    	sta[++top]=x;vis[x]=1;
    	for(R int i=h[x];i;i=edge[i].nex){
    		R int xx=edge[i].to;
    		if(!dfn[xx]){
    			Tarjan(xx);
    			low[x]=min(low[x],low[xx]);
    		}
    		else if(vis[xx])low[x]=min(low[x],dfn[xx]);
    	}
    	if(dfn[x]==low[x]){
    		R int now=-1;
    		cnt++;
    		while(now!=x){
    			now=sta[top];
    			top--;
    			col[now]=cnt;
    			siz[cnt]++;
    			vis[now]=0;
    		}
    	}
    }
    inline void init(){
    	tot=num=top=ans=cnt=0;
    	memset(h,0,sizeof(h));
    	memset(dfn,0,sizeof(dfn));
    	memset(low,0,sizeof(low));
    	memset(vis,0,sizeof(vis));
    	memset(siz,0,sizeof(siz));
    	memset(sta,0,sizeof(sta));
    	memset(col,0,sizeof(col));
    	memset(ru,0,sizeof(ru));
    	memset(dp,-1,sizeof(dp));
    }
    inline void topsort(){
    	queue<int> q;
    	while(!q.empty())q.pop();
    	for(R int i=1;i<=cnt;i++)
    		if(!ru[i])q.push(i),dp[i]=siz[i];
    	while(!q.empty()){
    		R int x=q.front();q.pop();
    		for(R int i=h[x];i;i=edge[i].nex){
    			R int xx=edge[i].to;
    			dp[xx]=max(dp[x]+siz[xx],dp[xx]);
    			--ru[xx];
    			if(!ru[xx])q.push(xx);
    		}
    	}
    }
    inline int search(R int x){
    	if(dp[x]!=-1)return dp[x];
    	R int res=siz[x];
    	for(R int i=h[x];i;i=edge[i].nex){
    		R int xx=edge[i].to;
    		res=max(search(xx)+siz[x],res);
    	}
    	return dp[x]=res;
    }
    int main(){
    	read(T);
    	while(T--){
    		read(n);read(m);init();
    		for(R int i=1;i<=m;i++)
    			read(u[i]),read(v[i]),add(u[i],v[i]);
    		for(R int i=1;i<=n;i++)	
    			if(!dfn[i])Tarjan(i);
    		tot=0;memset(h,0,sizeof(h));
    		for(R int i=1;i<=m;i++)
    			if(col[u[i]]!=col[v[i]])
    				add(col[u[i]],col[v[i]]),ru[col[v[i]]]++;
    		//记忆化搜索 
    		for(R int i=1;i<=cnt;i++)
    			ans=max(ans,search(i));
    		//拓扑排序 
    		topsort();
    		for(R int i=1;i<=cnt;i++)
    			ans=max(ans,dp[i]);
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    pytorch-卷积基本网络结构-提取网络参数-初始化网络参数
    pytorch-mnist神经网络训练
    python 面对对象 类(继承, 多态)
    注意机制CBAM
    python sqlalchemy 进行 mysql 数据库操作
    python pymysql 连接 mysql数据库进行操作
    mysql数据库基础
    python正则表达式解析(re)
    python 装饰器 (test = submit(test))
    对opencv读取的图片进行像素调整(1080, 1920) 1.cv2.VideoCapture(构造图片读取) 2.cv2.nameWindow(构建视频显示的窗口) 3.cv2.setWindowProperty(设置图片窗口的像素) 4.video_capture(对图片像素进行设置)
  • 原文地址:https://www.cnblogs.com/ZAGER/p/9921720.html
Copyright © 2020-2023  润新知