UVA11324_The Largest Clique_tarjan求强连通分量+DP求最长路
来源:互联网 发布:凯迪网络手机版 编辑:程序博客网 时间:2024/05/22 07:52
题意:
给一个图,求它的一个最大子图,使得图中任意两点之间都至少有一条路径【注意是两点之间有路径,而不是可以到达任意一点,所以不是强连通分量】
【PS:题中给的传递闭包其实是个迷惑,没有用,因为在原图上做,和在传递闭包的图上做是完全一样的】
题解:
先求出图中的所有强连通分量,将每个分量缩为一点使之成为一个DAG图,这样在这个无环图中,找子图使得满足条件
关键:
把问题“使得子图中任意两点之间都至少有一条路径”转化成“求一条最长路径”
这个非常关键,反正我刚开始挺难想的,不过推一推确实是这样,由于任意两点之间都有路,所以所有的路都可以压缩到同一条路径上,如果不能压缩,说明这个子图一定存在两点之间没有有向路径
而求最长路的问题又可以用DP来做,状态转移方程为 dp[u]=val[u]+max(dp[v])
其中,v是u的全部子节点,val[u]为当前标号为u的强连通分量中的结点个数,这样就可以求出来最大子图了
原题:
Problem B: The Largest Clique
Given a directed graph G, consider the following transformation. First, create a new graphT(G) to have the same vertex set as G. Create a directed edge betweentwo vertices u and v in T(G) if and only if there is a pathbetween u and v in G that follows the directed edges only in the forwarddirection. This graph T(G) is often called the transitive closure of G.
We define a clique in a directed graph as a set of vertices U such thatfor any two vertices u and v in U, there is a directededge either from u to v or from v to u (or both).The size of a clique is the number of vertices in the clique.
The number of cases is given on the first line of input. Each test case describes a graph G.It begins with a line of two integersn and m, where 0 ≤ n ≤ 1000 is the number ofvertices of Gand 0 ≤ m ≤ 50,000 is the number of directed edges of G.The vertices of G are numbered from 1 to n.The following m lines contain two distinct integers u and vbetween 1 and n which definea directed edge from u to v in G.
For each test case, output a single integer that is the size of the largest clique in T(G).
Sample input
15 51 22 33 14 15 2
Output for sample input
4
代码:
RunID User Problem Result Memory Time Language Length Submit Time
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<stack>#define N 1005#define M 50005using namespace std;int dfs_time;int dfn[N],low[N];int color[N];int dfs_color;int n,m;struct MyStruct{int u,v;}edge[M];vector<int>f[N];vector<int>DAG[N];//存缩点后的图stack<int>sta;int visited[N];int in_stack[N];//判断是否在栈中int dp[N];int val[N];//即每个强连通分量中的结点个数int vis_DAG[N];//标记DAG图中的缩点有没有被访问过int find_min(int a,int b){return a<b?a:b;}void tarjan(int u){dfn[u]=low[u]=++dfs_time;visited[u]=1;sta.push(u);in_stack[u]=1;int child;for (int i = 0; i <f[u].size() ; i++){child=f[u][i];if (!visited[child]){tarjan(child);low[u]=find_min(low[u],low[child]);}else if(in_stack[child]){low[u]=find_min(low[u],dfn[child]);}}if (dfn[u]==low[u])//说明u是当前连通分量的根{dfs_color++;do//弹出当前强连通分量{child=sta.top();color[child]=dfs_color;sta.pop();in_stack[child]=0;val[dfs_color]++;} while (u!=child);}}void dp_DAG(int u)//这里的u是强连通分量的缩点的标号{vis_DAG[u]=1;int max=0;int child;for (int i = 0; i < DAG[u].size(); i++){child=DAG[u][i];if (!vis_DAG[child]){dp_DAG(child);}if (max<dp[child]){max=dp[child];}}dp[u]=val[u]+max;//如果dfs搜到叶子结点,就直接到这一步,此时max=0,恰好满足dp[u]=val[u]}int main(){int i,j,a,b,t;int point_u,point_v;int ans;scanf("%d",&t);while (t--){scanf("%d%d",&n,&m);for ( i = 0; i <=n ; i++){f[i].clear();DAG[i].clear();}if (!sta.empty()){sta.pop();}memset(visited,0,sizeof(visited));memset(val,0,sizeof(val));memset(in_stack,0,sizeof(in_stack));memset(dp,0,sizeof(dp));memset(vis_DAG,0,sizeof(vis_DAG));dfs_time=0;dfs_color=0;ans=0;for ( i = 1; i <=m ; i++)//输入,存边,存图{scanf("%d%d",&a,&b);edge[i].u=a;edge[i].v=b;f[a].push_back(b);}for ( i = 1; i <=n ; i++)//求强连通分量{if (!visited[i]){tarjan(i);}}for ( i = 1; i <=m ; i++)//存DAG图{point_u=color[edge[i].u];point_v=color[edge[i].v];DAG[point_u].push_back(point_v);}for ( i = 1; i <=dfs_color ; i++){if (!vis_DAG[i]){dp_DAG(i);}}for ( i = 1; i <=dfs_color; i++){if (dp[i]>ans){ans=dp[i];}}printf("%d\n",ans);}return 0;}
- UVA11324_The Largest Clique_tarjan求强连通分量+DP求最长路
- tarjan求强连通分量
- tarjan 求强连通分量
- FZOJ1638求强连通分量
- tarjan求强连通分量
- Tarjan求强连通分量
- tarjan求强连通分量
- Tarjan求强连通分量
- 训练赛 Grouping(强连通分量缩点 + DAG求最长路)
- poj 3592 Instantaneous Transference (借助强连通分量求缩点在建图spfa求最长路)
- zoj3795 Grouping --- 强连通,求最长路
- 上白泽慧音 题解 ---- tarjan求强连通分量
- Tarjan算法求强连通分量
- 求图的强连通分量
- 求强连通分量的Tarjan算法
- POJ 1236 (Tarjan求强连通分量)
- tarjan求强连通分量模板
- hdu 4587 (求强连通分量)
- EPSG4326
- MFC中ON_UPDATE_COMMAND_UI和ON_COMMAND消息区别
- OpenCV命名规则
- Simplify Path
- Linux下用g++编译c程序
- UVA11324_The Largest Clique_tarjan求强连通分量+DP求最长路
- CF 192 DIV.2
- POJ题目分类
- J2EE基于MVC的各层的设计原则及其编写注意事项
- ETL的过程原理和数据仓库建设
- 130720CF解题报告
- 判断顶点是否位于三角形内
- ZK grid or list数据多列排序
- UVAlive 5864 Register Allocation 题解