UVa 11234 The Largest Clique

找最长的连接的点的数量。用tarjan缩点,思考可知每一个强连通分量里的点要么都选,要么都不选(走别的路),可以动规解决。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<vector>
 5 #include<cstring>
 6 using namespace std;
 7 const int mxn=12000;
 8 int top,stack[mxn];
 9 bool inst[mxn];
10 int cnt,dnow;
11 int dfn[mxn],low[mxn];
12 int belone[mxn];
13 int ptcnt[mxn];
14 int dp[mxn];
15 vector<int> e[mxn];//邻接表
16 vector<int> pt[mxn];//缩点后的点集
17 void clear(){
18     cnt=0;dnow=0;top=0;
19     memset(dfn,-1,sizeof(dfn));
20     memset(inst,false,sizeof(inst));
21     memset(dp,0,sizeof dp);
22     memset(ptcnt,0,sizeof ptcnt);
23     memset(belone,0,sizeof belone);
24     for(int i=1;i<mxn;i++) e[i].clear();
25     for(int i=1;i<mxn;i++) pt[i].clear();
26 }
27 int n,m;
28 void tarjan(int s){
29     int v=0,i;
30     dfn[s]=++dnow;
31     low[s]=dfn[s];
32     inst[s]=true;
33     stack[++top]=s;
34     int si=e[s].size();
35     for(i=0;i<si;i++){
36         v=e[s][i];
37         if(dfn[v]==-1){
38             tarjan(v);
39             low[s]=min(low[v],low[s]);
40         }
41         else if(inst[v]){
42             low[s]=min(dfn[v],low[s]);
43         }
44     }
45     if(dfn[s]==low[s]){
46         cnt++;
47         do{
48             v=stack[top--];
49             belone[v]=cnt;
50             inst[v]=false;
51         }while(s!=v);
52     }
53     return;
54 }
55 int find(int x){//动规
56     if(pt[x].size()==0)return dp[x]=ptcnt[x];
57     if(dp[x])return dp[x];
58     int mx=0;
59     for(int i=0;i<pt[x].size();i++){
60         mx=max(mx,find(pt[x][i]));
61     }
62     dp[x]=mx+ptcnt[x];
63     return dp[x];
64 }
65 void solve(){//统计缩完点之后的连通情况
66     int i,j,k;
67     for(i=1;i<=n;i++){
68         ptcnt[belone[i]]++;
69         for(j=0;j<e[i].size();j++){
70             int v=e[i][j];
71             if(belone[i]!=belone[v])
72                 pt[belone[i]].push_back(belone[v]);
73         }
74     }
75     int ans=0;
76     for(i=1;i<=cnt;i++)ans=max(ans,find(i));
77     printf("%d\n",ans);
78     return;
79 }
80 int main(){
81     int T;
82     scanf("%d",&T);
83     while(T--){
84         scanf("%d%d",&n,&m);
85         clear();
86         int i,j;
87         int u,v;
88         for(i=1;i<=m;i++){
89             scanf("%d%d",&u,&v);
90             e[u].push_back(v);
91         }
92         for(i=1;i<=n;i++){//缩点
93             if(dfn[i]==-1)tarjan(i);
94         }
95         solve();
96     }
97     return 0;
98 }
时间: 2024-10-30 00:17:39

UVa 11234 The Largest Clique的相关文章

UVA - 11324 The Largest Clique 强连通缩点+记忆化dp

题目要求一个最大的弱联通图. 首先对于原图进行强连通缩点,得到新图,这个新图呈链状,类似树结构. 对新图进行记忆化dp,求一条权值最长的链,每个点的权值就是当前强连通分量点的个数. /* Tarjan算法求有向图的强连通分量set记录了强连通分量 Col记录了强连通分量的个数. */ #include <iostream> #include<cstring> #include<cstdio> #include<string> #include<algo

uva 11324 The Largest Clique(强连通分量缩点+DAG动态规划)

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299 题意:输入n和m,有n个点和m条有向边,求出一个节点集合包括的节点个数最多,而且该节点内的不论什么两点a,b,要么a能到达b,要么b能到达a,要么a和b互相到达. 思路:强连通分量缩点形成有向无环图DAG,把缩点后的每一个点的权值置为该强连通分量的节点个

UVA 11324 - The Largest Clique(强连通分量+缩点)

UVA 11324 - The Largest Clique 题目链接 题意:给定一个有向图,要求找一个集合,使得集合内任意两点(u, v)要么u能到v,要么v能到u,问最大能选几个点 思路:强连通分量,构造出scc之后,缩点,每个点的权值是集合点个数,然后做一遍dag找出最大权值路径即可 代码: #include <cstdio> #include <cstring> #include <vector> #include <stack> #include

uva 11324 The Largest Clique(图论-tarjan,动态规划)

Problem B: The Largest Clique Given a directed graph G, consider the following transformation. First, create a new graph T(G) to have the same vertex set as G. Create a directed edge between two vertices u and v in T(G) if and only if there is a path

UVA 11324 The Largest Clique (强连通分量缩点,图DP)

题目: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=25&page=show_problem&problem=2299 题意: 给你一个有向图,求一个点集合的最大大小,使得此点集合中对于任意点对(u,v),有从u到v或者从v到u的边 方法: 先找强连通分量缩点,每个强连通分量显然满足条件,然后在缩点后的图中找到一条权值最大的路径,权值为此路径的点权之和,点权为这个

UVA - 11324 The Largest Clique (DAG + 强连通分量)

题目大意:给出一张有向图G,求一个结点数最大的结点集,使得该点集中任意两个结点u和v满足: 要么u可到达v,要么v可以到达u(u和v互相可达也可以) 解题思路:u和v相互可达的时候,就是两个结点在同一个强连通分量内的时候 首先要保证集合里面的点可达:强连通分量就满足集合内的点都相互可达.所以第一件事就是找出所有的强连通分量,并统计出每个强连通分量内的结点数 然后找出每个强连通分量之间的关系,也就是找出两个强连通分量之间的桥,连接可连接的强连通分量 最后将每个强连通分量收缩,得到SCC图.此时的S

UVA 11324.The Largest Clique tarjan缩点+拓扑dp

题目链接:https://vjudge.net/problem/UVA-11324 题意:求一个有向图中结点数最大的结点集,使得该结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相互可达也可以). 思路:同一个强联通分量中满足结点集中任意两个结点u和v满足:要目u可以到达v,要么v可以到达u(相互可达也可以).把强联通分量收缩点后得到scc图,让每个scc结点的权值等于他的结点数,则求scc图上权最大的路径.拓扑dp,也可以直接bfs,但是要建立一个新的起点,连接所有入度为0

UVA 11324 The Largest Clique

给出一个有向图,求一个最大的结点集合,任意两个点u,v.u可到达v或v可到达u. 一个强连通分量肯定一起选的.所以先找出所有scc,然后缩点以后跑DAG上的dp. 注意0,0这组数据 #include<bits/stdc++.h> using namespace std; const int maxn = 1005,maxm = 5e5+1; int head[maxn],to[maxm],nxt[maxm]; void addEdge(int u,int v,int i) { to[i] =

Uva 11324 The Largest Clique【强连通 DAG动规 spfa】

白书上的例题 做一遍tarjan后,缩点,每一个scc节点的权为它的结点数,做一次DAG上的动规,求出路径上的最大点权和,就可以了 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<stack> 6 #include<vector> 7 using namespace std; 8 9 const i